Here it comes, GD32F103 quickly replaces STM32F103
[Copy link]
1. Similarities**
1). The peripheral pins are PIN TO PIN compatible, and the multiplexing functions on each pin are exactly the same.
2). The chip internal registers, external IP register addresses and logical addresses are exactly the same, but some register default values are different, and the design timing of some peripheral modules is different from STM32. This difference is mainly reflected in the software modification, see below for details.
3). Compilation tools: exactly the same, for example: KEIL, IAR
4). The model naming method is exactly the same, so you only need to find the model with the same suffix to replace it, for example: STM32F103C8T6 and GD32F103C8T6.
5). Simulation tools: JLINK STLink Ulink GDLINK
2. Differences in peripheral hardware
3. Things to note when replacing hardware
From the above introduction, we can see that the GD32F103 series and the STM32F103 series are compatible, but there are also some things to note.
1) BOOT0 must be connected to 10K pull-down or GND, and ST can be left floating. This is very important.
2) The RC reset circuit must be present, otherwise the MCU may not work properly. Sometimes the ST one can be omitted.
3) Sometimes it is found that the emulator cannot be connected. Because the swd interface driving capability of GD is weaker than that of ST, there are several ways to solve it:
a. Make the line as short as possible;
b. Reduce the SWD communication rate;
c. Connect SWDIO to 10k pull-up and SWCLK to 10k pull-down.
4) When using battery power, pay attention to the working voltage of GD. For example, if it drops to the range of 2.0V~2.6V, ST can still work, but GD may not start or work abnormally.
4. Things that need to be modified when using ST standard library development
1). GD has strict requirements on timing. When configuring peripherals, you need to turn on the clock before configuring the peripherals. Otherwise, the peripherals may not be configured successfully. ST can be configured first and then turn on the clock.
2) Modify the external crystal oscillator start-up timeout. Skip this step if you don’t need an external crystal oscillator.
Reason: There is a difference between the startup time of GD and ST. In order to reset the GD MCU more accurately.
Modification:
Change the macro definition:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)
to:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF)
3) GD32F10X flash takes zero wait time, while ST requires 2 wait cycles. Therefore, some codes for precise delay or simulation of IIC or SPI may need to be modified.
Reason: GD32 uses patented technology to improve the code execution speed at the same operating frequency.
Modification: If you use for or while loops for precise timing, the timing will shorten the loop time due to the faster code execution speed, so you need to simulate and recalculate the design delay. Using the Timer has no effect.
4) Set read protection in the code. If you use external tools such as JFLASH or offline programmer to set read protection, you can skip this step.
After writing the KEY sequence, you need to read this bit to confirm that the key has taken effect. Modify as follows:
A total of four functions need to be modified:
FLASH_Status FLASH_EraseOptionBytes(void);
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
uint32_t FLASH_GetWriteProtectionOptionByte(void);
FlagStatus FLASH_GetReadOutProtectionStatus(void);
5) GD and ST have different flash Erase and Program times, modify as follows:
6) If the flash is larger than 256K, please note that this item can be ignored if it is smaller than 256K.
Unlike ST, GD has the concept of partitioning in its flash. The first 256K is called the code area, where the CPU executes instructions with zero waiting time. The area outside this range is called the dataZ area. There is no difference between the two in terms of erase and write operations, but there is a big difference in read operation time. The code in the code area has zero waiting time, while the execution of the code in the data area has a large delay. The code execution efficiency is one order of magnitude slower than that in the code area. Therefore, it is usually not recommended to run code with high real-time requirements in the data area. To solve this problem, you can use the method of distributed loading, such as putting the initialization code, image code, etc. in the data area.
7) ADC acquisition
a> The ADC channel should be configured as analog input. The chip defaults to floating input. If it is not configured as analog input, ST can collect normally, but GD cannot
. b> The ADC clock is not manually divided and the maximum operating frequency is within 14Mhz. ST can collect normally, but GD cannot.
c> After the ADC is enabled, a delay of no less than 20us needs to be added.
d> The sampling accuracy is not as good as STM32f103. GD32f103 has this problem. If the ADC accuracy requirement is not high, it can be selected. You can choose PIN TO PIN compatible F103 series GD32E103 and GD32F303 series to solve it.
Summary: So far, after the above modifications, you can use ST's code to operate without using the code of USB and network complex protocols.
Additional:
1. To modify or distinguish the code of GD32 and STM32, you can use the following code:
2. GD's main frequency supports 108MHz. Sometimes you need to provide the main frequency. Here is a 96MHZ reference:
static void SetSysClockTo96(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOC,!ENABLE);
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 12 = 96 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL12);
#else
#if 0
/* PLL configuration: PLLCLK = HSE * 12 = 96 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL12);
#else
// RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
// RCC_CFGR_PLLMULL));
//RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE|(1<<17));
//RCC->CFGR &= ~(RCC_CFGR_PLLMULL);
//RCC->CFGR |= (uint32_t)(1<<27u);
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | (1<<27)|(7<<18)|(1<<17));
#endif
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
for(StartUpCounter=0;StartUpCounter<0x200;StartUpCounter++);
for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
|