在一些新的 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.0\Projects\NUCLEO-L452RE\Examples\FLASH\FLASH_FastProgram 例程,对 \STM32Cube_FW_G0_V1.2.0\Projects\NUCLEO-G070RB\Examples\FLASH\FLASH_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 编程代码。