2023最新STM32F10X移植GD32F30X注意事项

[复制链接]
 楼主| 聚沃科技 发表于 2023-6-20 00:02 | 显示全部楼层 |阅读模式
本帖最后由 聚沃科技 于 2023-6-20 14:38 编辑

#技术资源# #申请原创#
1. System 模块使用注意事项

1.1 HXTAL 时钟丢失后,程序如何运行

程序使用外部晶振正常运行之后,如果将外部晶振去掉或者短路,GD32F30x 的程序不会取指执行。若将晶振重新恢复正常,程序会接着之前的地址运行,如果程序对丢时钟这种场景有特殊要求,应用中需要手动使能时钟安全系统,在其中做相关的保护措施。

1.2 如何区分 standby 复位和上电复位

仅通过 RCU 的 RCU_RSTSCK 寄存器无法区分是 standby 复位还是上电复位,需要结合查询 PMU 的 PMU_CS 寄存器解决问题。

1.3 HSE 注意事项

GD32F30x 外部晶体起振时间会比 STM32F10x 系列要长,所以原有的晶体超时时间需要加大:
  1. #define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500);
  2. /*!< Time out for HSE start up */


调整前:
  1. #define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF);
  2. /*!< Time out for HSE start up */


调整后:
  1. #define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF);
  2. /*!< Time out for HSE start up */

1.4 如何通过软件区分 GD32 和 STM32

GD32F30x 在设计阶段,已经预留了相关寄存器,用户只需要软件读取寄存器,即可获取到相关的型号信息,GD32F30x 每个型号此处值都为固定值。
  1. Code_Num=*( uint32_t *)( 0x40022100 );

1.5 GD32F30x Flash 取值零等待,软件方面注意事项

GD32F30x 系列 Flash 为零等待设计,在同主频下,带来了更高的性能体验。如果用户代码有用到 for 循环或者是 while 循环语句来做延时,延时时间在GD32F30x系列上会变短,需要适当的加大延时参数或改用Timer来做延时函数。

1.6 GD32F30x 上电启动异常常见原因

1.6.1 检查板子上 Boot 0 引脚是否悬空,GD32F30x 运行用户程序必须要求 Boot0经 10K 电阻接 GND;

1.6.2 如果板子上有大功率器件(Wifi、GSM、GPS 等),检查大功率器件开启瞬间VDD 是否存在跌落情况,如存在跌落可以适当加大电源输出端的负载电容;

1.6.3 观察芯片的复位管脚,复位管脚是否一直处于拉低状态,检查是否供电异常或者是芯片硬件看门狗使能了,芯片处于反复复位状态。

1.7 MCU 无法正常使用 SWD 下载程序

1.7.1 接线异常,SWD 相关的调试口未正常接好;

1.7.2 芯片是否被读保护或者处于反复复位状态;

1.7.3 SWD 的调试线过长或者是通信速率过高,适当减短 SWD 数据线,同时降低SWD 速率;

1.7.4 按照硬件指南给 SWD 添加相应的上下拉电阻,提高通信抗干扰能力。

1.8 MCU 上电时间较长

由于设计架构差异,GD32F30x 比 STM32F10x 的上电时间和 Standby 唤醒时间较长,时间约 144ms,若对时间没有要求,可忽略。

1.9 代码超过 256K 后执行速度慢

GD32F30x 系列的 Flash 分为 Code 区(前 256K)和 Data 区(256K 以后的区域),二者在擦写操作上没有区别,但是读操作时间上存在较大差别,Code 区代码取值零等待,Data 区执行代码会有较长延时。应用中如果涉及该架构影响到使用可以通过分散加载来改善,具体做法参考分散加载应用文档。

2. CAN 模块使用注意事项

2.1 CAN 发送出现 ACK 错误

假如出现类似 ACK 出错的问题,可以修改采样点,一般做法是将 BS1 值增大,BS2 减小。

2.2 CAN 接收异常,接收两帧数据会丢一包数据

STM32 固件库会调用 CAN_FIFORelease 函数,如果手动多调用一次清缓存的动作会导致 CAN 接收丢包,也就是软件中无需主动调用 CAN_FIFORelease 函数,CAN FIFO 会被自动释放。

3. 低功耗注意事项

3.1 在 Stop 模式下,少数芯片功耗偏高

为了使功耗恢复正常,需要将没用到的 IO 口全部配置成模拟输入(AN)模式,芯片内部未引出来的也要配置。

3.2 在 Stop 模式下,概率性不能唤醒

在不断进出 Stop,并且不断有 timer 或者 systick 中断时,运行很长时间后,在 Stop模式下有概率性的无法唤醒。

解决方案:

当进入 Stop 时(WFI/WFE),屏蔽掉除唤醒源中断外的所有中断,出 Stop 之后再打开其他中断,代码修改如下。

  1. void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
  2. {
  3. uint32_t tmpreg = 0;
  4. static uint32_t reg_snap[ 4 ];
  5. /* Check the parameters */
  6. assert_param(IS_PWR_REGULATOR(PWR_Regulator));
  7. assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
  8. /* Select the regulator state in STOP mode ---------------------------------*/
  9. tmpreg = PWR->CR;
  10. /* Clear PDDS and LPDS bits */
  11. tmpreg &= CR_DS_MASK;
  12. /* Set LPDS bit according to PWR_Regulator value */
  13. tmpreg |= PWR_Regulator;
  14. /* Store the new value */
  15. PWR->CR = tmpreg;
  16. /* Set SLEEPDEEP bit of Cortex System Control Register */
  17. SCB->SCR |= SCB_SCR_SLEEPDEEP;
  18. reg_snap[ 0 ] = (*(volatile uint32_t *)(0xE000E010));//REG32( 0xE000E010 );
  19. reg_snap[ 1 ] = (*(volatile uint32_t *)(0xE000E100));//REG32( 0xE000E100 );
  20. reg_snap[ 2 ] = (*(volatile uint32_t *)(0xE000E104));//REG32( 0xE000E104 );
  21. reg_snap[ 3 ] = (*(volatile uint32_t *)(0xE000E108));//REG32( 0xE000E108 );
  22. (*(volatile uint32_t *)(0xE000E010)) &= 0x00010004; //( 0xE000E010 )
  23. (*(volatile uint32_t *)(0xE000E180)) = 0XFF7FF83D; //( 0xE000E180 )
  24. (*(volatile uint32_t *)(0xE000E184)) = 0XBFFFF8FF; //( 0xE000E184 )
  25. (*(volatile uint32_t *)(0xE000E188)) = 0xFFFFFFFF; //( 0xE000E188 )
  26. /* Select STOP mode entry --------------------------------------------------*/
  27. if(PWR_STOPEntry == PWR_STOPEntry_WFI)
  28. {
  29. /* Request Wait For Interrupt */
  30. WFI();
  31. }
  32. else
  33. {
  34. /* Request Wait For Event */
  35. SEV();
  36. WFE();
  37. WFE();
  38. }
  39. (*(volatile uint32_t *)(0xE000E010)) = reg_snap[ 0 ] ;
  40. (*(volatile uint32_t *)(0xE000E100)) = reg_snap[ 1 ] ;
  41. (*(volatile uint32_t *)(0xE000E104)) = reg_snap[ 2 ] ;
  42. (*(volatile uint32_t *)(0xE000E108)) = reg_snap[ 3 ] ;
  43. /* Reset SLEEPDEEP bit of Cortex System Control Register */
  44. SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
  45. }

4. ADC 模块使用注意事项

4.1 ADC 采集数据异常问题分析

4.1.1. ADC 通道的采集引脚未配置为模拟输入,GD32 要求通道 IO 口必须配置为模拟输入;

4.1.2. ADC 时钟过高,ADC 采样时钟高于 40M 获取到的数据不具有参考意义;

4.1.3. ADC 不耐 5V 的 IO 口被接入超过 VDDA 的电平信号;

4.1.4. ADC 采样值偏小或不稳定,应该适当的降低 ADC 时钟,加大采样周期的值。

4.2 ADC1 和 ADC2 同步模式下,注意事项

如果 ADC1 和 ADC2 同步采集,ADC2 是跟着 ADC1 同步触发,此时 ADC2 的注入组的触发方式需要手动配置成软件触发(默认是 TIMER1_TRGO),否则可能导致 ADC 注入组无数据。

4.3 ADC_CR2 中的 ADCON 使用注意事项

ADC 使能以后需要在代码里面插入 1 个通道的 ADC 转换周期以上;

  1. /* Enable ADC1 */
  2. ADC_Cmd(ADC1, ENABLE);
  3. Delay_us(20);
4.4 ADC 查询法采集数据,出现通道错乱的情况

ADC 使用查询法采集数据时,如果使能了 ADC 的 SCAN 模式,就有可能会出现ADC 数据错乱的情况;ADC 采集通道 SCAN 功能只适用于多通道注入采样和DMA 模式。

4.5 ADC 在每次复位之后采样值有偏差

由于 MCU 上电或者复位阶段,ADC 校准时,电源不稳定,导致校准时出现偏差,ADC 值采样均出现偏大或者偏小,可以关闭校准,或者等电源稳定后再校准解决该问题。

  1. /* ADC calibration and reset calibration */
  2. adc_calibration_enable(ADCx);

5 RCU 模块使用注意事项

当 IAP 时,使用 GD32 的固件作为 boot,跳转到 STM32 固件库的 APP 后,可能造成系统时钟不对,例如 uart 打印异常,timer 异常。

GD32F30x 系列 MCU 最高主频可以运行 120MHz,PLL 倍频参数比 STM32 的多几个 bit,如下,出现异常时,需要跳转前将相关的 bit 复位。
图片1.png
GD32 的 CFG0 寄存器的 bit30 bit28 bit27 为有效位。
图片2.png
STM32 的 RCC_CFGR 寄存器的 bit30 bit28 bit27 为保留位。


6 SPI 模块使用注意事项
6.1 SPI 通信 BSY 标志位

在 SPI 程序编写的过程中,轮询使用 BSY 作为通信标志位,导致传送数据丢失或者是错误。
这主要是因为 GD32 的 BSY 标志位不是在写入 DR 后就置位的,而是发送完第一个 bit 才被置位,传输过程中不要使用 BSY 作为每次传输的判断,使用 TXE 和
RXNE 来进行判断。
  1. /*send data*/
  2. while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY) ==SET))
  3. while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) !=SET))
  4. /* Deselect the FLASH: Chip Select high */
  5. SPI_FLASH_CS_HIGH();
  6. /*receive data*/
  7. while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY) ==SET))
  8. while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) !=SET))//send byte
  9. /* Deselect the FLASH: Chip Select high */
  10. SPI_FLASH_CS_HIGH();

6.2 SPI 使能之后配置参数不生效
当需要修改 SPI 模式或者速度的时候,需要将 SPI 先 disable,再修改参数,最后再 enable.

6.3 SPI 从机模式管脚模式
从机模式下 CLK、MISO、NSS 需要将 IO 配置成 Input_floating,才能正常工作。

7  UART DMA 注意事项
使用 UART DMA 发送数据的时候,可能丢掉一帧中的第一个 byte 数据,注意尽量不要在发送的时候频繁的开关 UART 发送,若测试无问题,可以忽略。
usart_transmit_config(USARTx,USART_TRANSMIT_ENABLE)假如要关闭 UART 发送,需要按照以下流程:先开启 usart_transmit_ enable 再去打开 dma_channel_enable,如下图。
图片3.png


8 LSE 驱动模式
GD32 MCU 的 RTC 驱动能力分四档,默认是强驱动能力,若不使用 GD32 本身的固件库,可能会强驱动改成弱驱模式,造成部分机器不起振,则需要将寄存器RCU_BDCTL 的 LXTALDRI[1:0]配置成 11。
图片4.png

图片5.png


9 USB 模块使用注意事项
USBD 通讯假如出现 PMOUIF 和 ERRIF 错误,可以通过屏蔽 CNTR_ESOFM 标 志 来解决该问题。
  1. /* IMR_MSK */
  2. /* mask defining which events has to be handled */
  3. /* by the device application software */
  4. #define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM
  5. | CNTR_SOFM| CNTR_ESOFM | CNTR_RESETM )//before fix
  6. #define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM
  7. | CNTR_SOFM| CNTR_RESETM )// after fix


10 Flash 模块使用注意事项

10.1 Flash 擦写差异
GD32 MCU Flash 执行速度快,但是写操作慢,所以在对 Flash 操作的时候需要修改下面几个函数:
  1. 修改 Flash 擦除和编程超时宏定义:
  2. #define EraseTimeout ((uint32_t)0xFFFFFFFF)//0x000B0000
  3. #define ProgramTimeout ((uint32_t)0xFFFFFFFF)//00002000
  4. 修改选项字节操作函数:
  5. FLASH_Status FLASH_EraseOptionBytes(void);
  6. FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
  7. FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
  8. FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);

  1. 在这四个函数写完 key( FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR =
  2. FLASH_KEY2;)
  3. 后添加两个__nop()语句或者是增加 如下语句:
  4. while((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set )
  5. {}
  6. #define CR_OPTWRE_Set ((uint32_t) 0x00000200) //Fix
  7. FLASH_Status FLASH_EraseOptionBytes(void)
  8. {
  9. uint16_t rdptmp = RDP_Key;
  10. FLASH_Status status = FLASH_COMPLETE;
  11. /* Get the actual read protection Option Byte value */
  12. if(FLASH_GetReadOutProtectionStatus() != RESET)
  13. {
  14. rdptmp = 0x00;
  15. }
  16. /* Wait for last operation to be completed */
  17. status = FLASH_WaitForLastOperation(EraseTimeout);
  18. if(status == FLASH_COMPLETE)
  19. {
  20. /* Authorize the small information block programming */
  21. FLASH->OPTKEYR = FLASH_KEY1;
  22. FLASH->OPTKEYR = FLASH_KEY2;
  23. /* if the previous operation is completed, proceed to erase the option bytes */
  24. FLASH->CR |= CR_OPTER_Set;
  25. FLASH->CR |= CR_STRT_Set;
  26. while(((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set)){};
  27. /* Wait for last operation to be completed */
  28. status = FLASH_WaitForLastOperation(EraseTimeout);}


10.2 Flash 操作地址差异
写 Flash,必须采用绝对地址,也就是 0x08000000 为首地址。而对于读操作,既可以使用绝对地址,也可以用相对地址 0x00000000。

获取更多移植文档:https://www.gd32bbs.com/docs/GD32MCU/yizhi.html

PDF下载:
游客,如果您要查看本帖隐藏内容请回复






 楼主| 聚沃科技 发表于 2023-6-20 00:07 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:11 编辑

 楼主| 聚沃科技 发表于 2023-6-20 08:44 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:13 编辑

 楼主| 聚沃科技 发表于 2023-6-20 08:46 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:16 编辑

 楼主| 聚沃科技 发表于 2023-6-20 08:46 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:16 编辑

 楼主| 聚沃科技 发表于 2023-6-20 08:53 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:17 编辑

 楼主| 聚沃科技 发表于 2023-6-20 08:55 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:17 编辑

 楼主| 聚沃科技 发表于 2023-6-20 10:28 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:17 编辑

 楼主| 聚沃科技 发表于 2023-6-20 10:29 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:17 编辑

 楼主| 聚沃科技 发表于 2023-6-20 10:31 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:18 编辑

 楼主| 聚沃科技 发表于 2023-6-20 10:54 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:18 编辑

 楼主| 聚沃科技 发表于 2023-6-20 10:59 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:18 编辑

 楼主| 聚沃科技 发表于 2023-6-20 12:46 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:22 编辑

 楼主| 聚沃科技 发表于 2023-6-20 12:48 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:22 编辑

 楼主| 聚沃科技 发表于 2023-6-20 12:54 | 显示全部楼层
本帖最后由 聚沃科技 于 2023-6-20 13:25 编辑

ljm9823 发表于 2023-6-20 14:07 | 显示全部楼层
ljm9823 发表于 2023-6-20 14:07 | 显示全部楼层
rongwinzip 发表于 2023-6-20 19:20 | 显示全部楼层
看看内容吧
shidonghan 发表于 2024-4-28 16:15 | 显示全部楼层
sss1024 发表于 2024-4-30 09:49 | 显示全部楼层
哈哈哈哈
您需要登录后才可以回帖 登录 | 注册

本版积分规则

170

主题

190

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部

170

主题

190

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部