被STM32G0快速编程难倒的,看这里

发布者:Qinghua2022最新更新时间:2023-02-07 来源: zhihu关键字:STM32G0  快速编程 手机看文章 扫描二维码
随时随地手机看文章

引言

在一些新的 STM32 系列中,比如 STM32L4、STM32G0、STM32G4 等,除了 Flash 标准编程之外,还可以支持 Flash 的快速编程。那么对于 STM32G0 来说,在使用快速编程时,有哪些需要注意之处?


难点

某STM32用户在其产品设计中,采用了 STM32G070RBT6,开发工程师希望在进行代码升级的时候使用快速编程来提高编程速度,但是写代码时遇到很多问题。而在目前的 STM32G0 的 Cube 库中并没有 FLASH_FastProgram 例程,所以客户希望得到一个参考例程来快速实现设计。


调研


1、了解问题

检查最新版本的STM32Cube_FW_G0_V1.3.0/Projects/STM32CubeProjectsList.html 文件,确实可以看到现有的 STM32G0Cube 库中并没有 FLASH_FastProgram 例程,根据参考手册,参考STM32Cube_FW_L4_V1.16.0ProjectsNUCLEO-L452REExamplesFLASHFLASH_FastProgram 例程,对 STM32Cube_FW_G0_V1.2.0ProjectsNUCLEO-G070RBExamplesFLASHFLASH_EraseProgram 进行修改以移植代码。以下就撰写例程代码时,需要注意的问题简单地介绍一下。


2、分析问题

首先,先来看一下 STM32L4 中 FLASH_FastProgram 例程中 readme.txt 对本示例的解释,可以看到这是一个演示如何配置和使用 API 函数对内部 Flash 存储器进行擦除和快速编程的示例。


先来看一下 FastProgram 最核心的函数 FLASH_Program_Fast()。


在 STM32L4Cube 中的 stm32l4xx_hal_flash,它是这么定义的:


static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)

而在 STM32G0Cube 中的 stm32g0xx_hal_flash,其定义是:


static __RAM_FUNC void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)

这两者有什么区别呢?就是在 STM32G0Cube 库中使用了__RAM_FUNC 指明了这个函数是位于 RAM 区域的。为什么呢?


第一个要点:对 Flash 进行快速编程的时候不允许对 Flash 进行读取,所以需要将这个快速编程的代码放置于 RAM 中运行,以避免对 Flash 进行命令读取。


那么,大家可能又有疑问了,那为什么 STM32L4Cube 中并没有使用__RAM_FUNC 关键字,STM32L452 的 Flash 是 single bank,难道它就不需要放到RAM 里?如果大家细心的话,可以看到STM32L4这个例程中的链接文件是 stm32l452xx_sram.icf,在icf 文件中定义了ROM的地址为 0x20000000~0x20015FFF,也就是说这个示例代码是跑在 RAM的,所以就不需要在这边使用__RAM_FUNC 关键字了。还可以在 STM32L4 示例代码中看到对整片 Flash 进行擦除而猜到这一点。从 STM32G0Cube 库中 FLASH_Program_Fast() 这个函数的定义,可以看出它是可以直接使用 stm32l452xx_flash.icf 将快速编程核心代码以外的其他代码都放在 Flash 上面跑的,这个可能更符合用户做 IAP 升级的习惯,当然,在这个情况下,我们就可能需要在程序中使用页擦除而不是整片擦除了。


第二个要点:因为 Flash 进行快速编程的时候不允许对 Flash 进行读取,所以还需要注意快速编程的源数据应该位于 RAM 而非 Flash,以避免对 Flash 进行数据读取。


因为在 Flash 快速编程的时候,需要将 64 个 word 一个行 (256 Bytes) 的数据写到目标地址中,所以也就是说快速编程时,还会去访问源数据,如果源数据放在Flash就会导致问题产生。下面,我们解答一个移植中常见问题。


在从 STM32L4 到 STM32G0 的移植中,直接将 STM32L4 示例代码中定义的源数据的数组代码:


/* Table used for fast programming */ 

static const uint64_t Data64_To_Prog[FLASH_ROW_SIZE] = {

0x0000000000000000, 0x1111111111111111, 

0x2222222222222222, 0x3333333333333333, 

0x4444444444444444, 0x5555555555555555, 

0x6666666666666666, 0x7777777777777777, 

0x8888888888888888,0x9999999999999999, 

0xAAAAAAAAAAAAAAAA,0xBBBBBBBBBBBBBBBB,

0xCCCCCCCCCCCCCCCC,0xDDDDDDDDDDDDDDDD, 

0xEEEEEEEEEEEEEEEE, 0xFFFFFFFFFFFFFFFF, 

0x0011001100110011, 0x2233223322332233, 

0x4455445544554455, 0x6677667766776677, 

0x8899889988998899,0xAABBAABBAABBAABB, 

0xCCDDCCDDCCDDCCDD,0xEEFFEEFFEEFFEEFF, 

0x2200220022002200, 0x3311331133113311, 

0x6644664466446644, 0x7755775577557755, 

0xAA88AA88AA88AA88,0xBB99BB99BB99BB99, 

0xEECCEECCEECCEECC, 0xFFDDFFDDFFDDFFDD};

原封不动地拷贝到 STM32G0 的项目中,在测试的时候,总是会发现程序会死在快速编程的过程中。最后检查才发现问题出现在这个数组的定义上。STM32L4 使用 stm32l452xx_sram.icf 定义了 ROM 的地址为 0x20000000~0x20015FFF,因此这个 const 关键字的数据实际上也是位于 RAM 中的。但是将这个数组搬到 STM32G0 的项目时,因为使用的是stm32l452xx_flash.icf,导致这个数组位于 Flash 中,在快速编程的时候程序就会去访问 Flash 读取源数据,就导致程序死在快速编程过程。所以,需要将数组修改为:


/* Table used for fast programming */ 

uint64_t Data64_To_Prog[FLASH_ROW_SIZE] = { 

0x0000000000000000, 0x1111111111111111, 

0x2222222222222222, 0x3333333333333333, 

0x4444444444444444, 0x5555555555555555, 

0x6666666666666666, 0x7777777777777777, 

0x8888888888888888,0x9999999999999999, 

0xAAAAAAAAAAAAAAAA,0xBBBBBBBBBBBBBBBB,

 0xCCCCCCCCCCCCCCCC,0xDDDDDDDDDDDDDDDD, 

 0xEEEEEEEEEEEEEEEE,0xFFFFFFFFFFFFFFFF,

0x0011001100110011,0x2233223322332233, 

0x4455445544554455, 0x6677667766776677, 

0x8899889988998899,0xAABBAABBAABBAABB, 

0xCCDDCCDDCCDDCCDD,0xEEFFEEFFEEFFEEFF, 

0x2200220022002200, 0x3311331133113311, 

0x6644664466446644, 0x7755775577557755, 

0xAA88AA88AA88AA88,0xBB99BB99BB99BB99, 

0xEECCEECCEECCEECC, 0xFFDDFFDDFFDDFFDD};

这样程序就可以正常运行。


第三个要点:使用在 Flash 上跑 IAP 代码进行快速编程的话,建议看一下参考手册里快速编程的步骤,在步骤中的第一步时使用 Page Erase 对当前页进行擦除后对当前页进行快速编程,每次一页,也就是“擦除当前页→快速编程当前页→擦除下一页→快速编程下一页→……”。


下面来仔细阅读参考手册,关注一下另外几个要点。


第四要点:关于时钟,在快速编程的过程中,CPU 的时钟频率(HCLK)不得低于 8MHz。这个在大家的应用中一般都是满足的,所以还好。另外,在“注”里边说明,FSTPG 位置 1 时,内部振荡器 HSI16 会自动使能,在 FSTPG 位清零时自动禁止,但 HSI16 之前已经通过 HSION 使能的情况除外。


第五要点:这一行 32 个双字必须连续写入,两个双字写入请求的最大时间间隔大约为 20us。如果后面的写入请求时间超出了这个范围,那么将导致 MISSERR 错误产生。一般来说,只要您使用的是库文件的函数,不用担心这个问题。


第六要点:在两次擦除之间,每一行的写入,高压持续时间不能大于8ms。一般来说,只要HCLK 的时钟保证在8MHz以上,对32个双字的连续写序列,时间上还是没问题的。如果真的程序没写好,导致存在这种情况,那么在芯片内部有个7ms 的检测机制,超时就会自动停止编程,并置位 FASTERR。


第七要点:关中断。至于为什么?大家都知道,就不多说了。如果大家使用 Cube 库,也可以看到在 FLASH_Program_Fast() 在进行关中断,但是示例中并没有恢复打开中断,所以大家在实际应用中根据情况看是否需要将中断打开。


3、问题解决

上面几个要点,如果软件工程师使用的是 STM32Cube 库,那么在撰写代码上最主要是检查一下前面三个要点的情况。后面几个要点稍微了解就可以了。


结论

Flash的快速编程可以节省编程的时间,但是在使用上因为有不少限制因素,使得它的软件设计比标准编程复杂,需要工程师细心调试。


建议

软件工程师在撰写Flash快速编程时,仔细阅读下参考手册,并参考本文中的各个要点,然后根据自己的实际应用情况,理清逻辑,来撰写完整的 Flash 编程代码。

关键字:STM32G0  快速编程 引用地址:被STM32G0快速编程难倒的,看这里

上一篇:STM32G0实战—定时器PWM应用
下一篇:STM32 SBSFU的实现与应用

推荐阅读最新更新时间:2024-11-13 12:33

MCU快速编程框架示例代码
很多朋友在单片机编程时都会遇到单片机编程框架问题,以下是一个MCU快速编程框架示例代码。在这个基础框架上,可以很方便的添加模块,通过测试可以在Kiel, AVRGCC, MPLABC18, PICC18, PICC16, ElanC, HoLTEkC下直接编译。是一个非常实用的小插件。 Happ_GUI.h .app_IR.h .app_ LED Color.h .app_Motor.h .app_Music.h .app_RF.h .drv_Adc.h .drv_Buzzer.h .drv_CPUIO.h .drv_DS1302.h .drv_DS18B20.h .drv_Eeprom.h .drv
[单片机]
MCU<font color='red'>快速</font><font color='red'>编程</font>框架示例代码
CRC校验编程和硬件快速校验探讨
引言 循环冗余校验(Cyclic Redundancy Check,CRC)是最为常用的计算机和仪表数据通信的校验方法。CRC码是一种线性分组码,编码简单但具有很强的检错纠错能力。除了各种嵌入式仪表、变频器等设备,还有一些数字型传感器的输出数据也提供CRC码,如数字温度传感器DS18B20、集成温湿度采集芯片SHT11等。但是,各厂商所提供的CRC校验多项式(用于同通信码模除)互有差别,且有CRC8和CRC16之分。另外,规定模除余数初始值所有的位有全清0或全置1之分(其CRC硬件生成电路不同),故其模除求余的运算过程也不相同。初接触者往往难以领晤,省略CRC校验使通信的可靠性降低。而不少C语言程序,运算时需要使用较多的RAM单元
[单片机]
CRC校验<font color='red'>编程</font>和硬件<font color='red'>快速</font>校验探讨
工程师笔记|STM32G0 复位后死机
引言 有客户反映,STM32G071RBT6 在使用 STM32CubeProgrammer 烧录完程序后只能运行一次,复位后,程序无法运行,如果掉电后重新上电,程序恢复正常。 问题描述 根据客户描述,该问题可通过以下步骤复现: 2.1. 测试代码的功能流程图 准备测试代码 App1 和 App2: 2.2. 问题复现步骤 操作步骤 (1) 在 STM32CubeProgrammer 中下载 应用程序 App1(如图 3),并设置 RDP=1(如图 4);然后断开 STM32CubeProgrammer 的连接,板子断电后重新上电; (2) 根据 log 提示(如图 5
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved