打印
[STM32G0]

TM32G0 快速编程要点

[复制链接]
938|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
micoccd|  楼主 | 2021-11-15 10:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前言
在一些新的 STM32 系列中, 比如 STM32L4、 STM32G0、 STM32G4 等,除了 Flash 标准编程之外,还可以支持 Flash 的快
速编程,那么对于 STM32G0 来说,在使用快速编程时,有哪些需要注意的地方呢?  

使用特权

评论回复
沙发
micoccd|  楼主 | 2021-11-15 10:09 | 只看该作者
问题
某客户在其产品的设计中,使用了 STM32G070RBT6。 客户希望在进行代码升级的时候使用快速编程来提高编程速度,但是
在写代码中遇到很多问题,而在目前的 STM32G0 的 Cube 库中并没有 FLASH_FastProgram 例程,所以客户希望得到一个参
考例程来加速他的设计。

使用特权

评论回复
板凳
micoccd|  楼主 | 2021-11-15 10:12 | 只看该作者
调研
1.了解问题
检查最新版本的 STM32Cube_FW_G0_V1.3.0/Projects/STM32CubeProjectsList.html 文件,确实可以看到在现有的
STM32G0Cube 库中并没有 FLASH_FastProgram 例程,所以学习一下参考手册,参考
\STM32Cube_FW_L4_V1.16.0\Projects\NUCLEO-L452RE\Examples\FLASH\FLASH_FastProgram 例程,对
\STM32Cube_FW_G0_V1.2.0\Projects\NUCLEO-G070RB\Examples\FLASH\FLASH_EraseProgram 进行修改以移植代码。
在撰写例程代码的时候,确实会遇到一些需要注意的问题,下面简单地介绍一下。

使用特权

评论回复
地板
micoccd|  楼主 | 2021-11-15 10:12 | 只看该作者
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)


使用特权

评论回复
5
micoccd|  楼主 | 2021-11-15 10:13 | 只看该作者
什么区别呢? 就是在 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 升级的习惯,当然,在这个情况下,我们
就可能需要在程序中使用页擦除而不是整片擦除了。

使用特权

评论回复
6
micoccd|  楼主 | 2021-11-15 10:14 | 只看该作者
第二个要点:因为 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};
这样就可以了。


使用特权

评论回复
7
micoccd|  楼主 | 2021-11-15 10:17 | 只看该作者
第三个要点:使用在 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()
在进行关中断,但是示例中并没有恢复打开中断,所以大家在实际应用中根据情况看是否需要将中断打开。

使用特权

评论回复
8
micoccd|  楼主 | 2021-11-15 10:18 | 只看该作者
3.问题解决
上面几个要点, 如果软件工程师使用的是 STM32Cube 库,那么在撰写代码上最主要是检查一下前面三个要点的情况。 后面
几个要点稍微看一下没有犯到就可以了。附上一个仅供参考的示例代码。

使用特权

评论回复
9
micoccd|  楼主 | 2021-11-15 10:19 | 只看该作者
结论
Flash 的快速编程可以节省编程的时间,但是在使用上因为有不少限制因素,使得它的软件设计比标准编程来得复杂,需要工
程师细心一点。

使用特权

评论回复
10
micoccd|  楼主 | 2021-11-15 10:20 | 只看该作者
建议
软件工程师在撰写 Flash 快速编程时, 仔细阅读下参考手册,并参考本文中的各个要点,然后根据自己的实际应用情况, 理清
逻辑, 来撰写完整的 Flash 编程代码。

使用特权

评论回复
11
HJD001| | 2021-11-16 10:26 | 只看该作者
非常有用!

使用特权

评论回复
12
qcliu| | 2021-12-9 18:54 | 只看该作者
有很多新手可以借鉴的地方

使用特权

评论回复
13
tfqi| | 2021-12-9 18:56 | 只看该作者
和其他系列相比有什么不一样的地方呢

使用特权

评论回复
14
wiba| | 2021-12-9 18:56 | 只看该作者
有很多编程的小技巧啊

使用特权

评论回复
15
zljiu| | 2021-12-9 19:00 | 只看该作者
这个容易上手吗

使用特权

评论回复
16
coshi| | 2021-12-9 19:03 | 只看该作者
确实非常好用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

700

帖子

1

粉丝