GD32F450替换ST32F429 部分flash速度慢问题解决

9 篇文章 0 订阅
  1. 由于st的芯片涨价,原来一片stm32f429ZGT6只要40多块钱,现在一片400多块钱,就这还没货,而GD32F450ZIT6现在100多块钱一片(之前20多一片),所以公司决定替换降本,选用pin to pin的GD32F450ZIT6替换ST芯片,任务就分配给我,直接烧录使用hal库的st应用代码调试,发现GD的片子串口中断方式接收数据,在波特率大于57600的情况下就会丢字节,大概50-100个字节就会丢失一个字节,但同样的代码在ST上完全正常。而使用GD提供的库函数,则串口完全正常,遂开始着手解决问题。
  2. 于是第一个考虑的是库函数的问题,开始对比Hal库与GD的标准库串口初始化的区别,经过两天的对比之后发现在底层操作上完全没有任何区别 = = ,同时感叹hal库看起来真让人头疼,从头到尾的函数指针,指到人逐渐崩溃。排除是库函数的问题。
  3. 排除掉库函数的问题,我就真的不知道是什么问题了,只好百度GD单片机问题汇总,最终发现GD的片子flash有高低速之分,而ST的全部为高速flash(贵有贵的道理哈),我用的这款GD芯片,flash一共是2M字节—高速区是flash的前256K字节(0x08000000-0x08040000),低速区是flash的后1792K字节(0x80400000-0x82000000),于是猜想是串口中断处理函数编译在了低速区flash,导致每次中断内代码执行时间过长,波特率越高,中断频率越高,也就自然会丢失字节。
  4. 有了猜想就开始验证----查看keil生成的.map文件发现,串口中断内的所有函数都编译在了低速区,也就是在地址0x80400000之后,那么到底低速区flash执行速度相较高速区慢了多少呢?于是使用一个定时器来测试同样的代码在高速区的执行速度与低速区的执行速度对比,代码如下:
//定时器时钟频率设定在1MHZ,计数方式为向上计数,上溢值设置为60000,因此CNT寄存器值每加1,就等于计时1us,所以这个计数最多可以计时60ms。
//清零CNT寄存器(当前计数值寄存器)
__HAL_TIM_SET_COUNTER(&htim6,0);
//开启定时器
HAL_TIM_Base_Start(&htim6);
//获取CNT寄存器值
time_began=__HAL_TIM_GET_COUNTER(&htim6);
//运行测试代码
TimeTest();
//再次获取CNT寄存器值
time_end=__HAL_TIM_GET_COUNTER(&htim6);
printf("TimeTest()函数耗时=%dus",time_end-time_began);
//关闭定时器
HAL_TIM_Base_Stop(&htim6);

使用以上代码测试发现,在ST上运行,TimeTest()函数耗时4到5us,在GD上运行,TimeTest()函数在高速区耗时3到4us;在低速区耗时57us之久!速度居然相差15倍之大…于是得出结论,GD-HighSpeedFlash>=ST-flash>>GD-LowSpeedFlash,好了,接下来要做的就是,如何把对耗时有严格要求的代码编译到高速区flash内,对耗时有严格要求的代码,例如 中断,实时系统(ucos、freertos)。步骤如下:

1


2,点击Linker,取消勾选[Use Memory Layout from Target Dialog],点击[Edit…]
在这里插入图片描述
3编辑.sct文件,比如说你要把main.c和stm32f4xx_it.c,stm32f4xx_hal_gpio.c编译在高速区,把user_a.c与user_b.c编译到低速区,那么你可以这样写:

;LR_IROM1 是flash 0x08000000-0x08040000 (高速区)区域
LR_IROM1 0x08000000 0x08040000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   main.o (+RO)
   ;*是通配符,写过脚本的应该都理解,不理解的自行百度,这样就把stm32f4xx_it.c,stm32f4xx_hal_gpio.c都编译进了高速区
   ;(+RO)代表将stm32f4xx*.c文件中的代码段,全局变量,静态变量编译进去。
   stm32f4xx*.o (+RO)
   
  }
  RW_IRAM1 0x20000000 0x00030000  {  ; RW data
   .ANY (+RW +ZI)
  }
  RW_IRAM2 0x10000000 0x00010000  {
   .ANY (+RW +ZI)
  }
}
;LR_IROM1 是flash 0x08040000 0x08200000(低速区)区域
LR_IROM2 0x08040000 0x08200000  {    ; load region size_region
  ER_IROM1 0x08040000 0x08200000  {  ; load address = execution address
   .ANY (+RO)
   ;同理,这样就把user_a.c,user_b.c都编译进了低速区
   user_*.o (+RO)
  }
}

这个文件就是一个脚本文件,规定了.c文件编译在flash中的地址,语法规则自行百度, ;号后是注释,这样就可以完美的把不同的.c文件编译进自己指定的flash区域了。
修改之后,GD的片子串口就不再丢数据了,根本原因就是将中断代码编译进了低速区。问题解决。
有兴趣可以看一下keil官网的这篇关于继承flash空间的sct语法,有大用:
Inheritance rules for load region address attributes
如果你觉得这篇文章还行,点个赞吧

  • 43
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: gd32f450和stm32并不是型号中的一个,而是两个不同的产品系列。gd32f450是GigaDevice生产的一系列32位ARM Cortex-M4微控制器,而stm32是STMicroelectronics生产的一系列32位ARM Cortex-M系列微控制器。 尽管它们都是基于ARM Cortex-M架构,但gd32f450和stm32之间有一些差异。首先,它们具有不同的制造商和技术支持。其次,它们的架构、内部组件和外设功能可能有所不同。由于其设计和功能特点的差异,gd32f450和stm32之间的软件开发、编程和驱动也会有所不同。 因此,选择使用gd32f450还是stm32取决于具体的项目需求、制造商支持和开发人员的经验。在选择时,我们需要综合考虑芯片的性能、功耗、成本、可用外设和开发工具等因素,并且需要对这两个产品系列有一定的了解,以便做出合适的选择。 ### 回答2: gd32f450和stm32是两个不同的型号。 gd32f450是GigaDevice公司的一款32位微控制器产品,主要基于ARM Cortex-M4内核,适用于各种嵌入式系统应用。它具有较高的性能、更低的功耗和多种接口,能够满足不同应用场景的需求。 而stm32是STMicroelectronics公司的一系列32位微控制器产品,也是基于ARM Cortex-M内核的。STM32系列包括了多个型号,适用于各种不同的应用领域,如工业控制、智能家居、汽车电子等。STM32系列具有丰富的外设和高度可定制性,广泛应用于全球各个领域。 尽管gd32f450和stm32都是32位微控制器产品,都基于ARM Cortex-M内核,但它们是不同公司的产品,具有不同的设计和特性。因此,不能说gd32f450和stm32是相同的型号。每个型号都有自己独特的特点和应用场景,需要根据具体需求选择合适的产品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值