
在一些新的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,它是这么定义的: staticvoidFLASH_Program_Fast(uint32_tAddress,uint32_tDataAddress) 而在STM32G0Cube中的stm32g0xx_hal_flash,其定义是: static__RAM_FUNCvoidFLASH_Program_Fast(uint32_tAddress,uint32_tDataAddress) 这两者有什么区别呢?就是在STM32G0Cube库中使用了__RAM_FUNC指明了这个函数是位于RAM区域的。为什么呢? 第一个要点:对Flash进行快速编程的时候不允许对Flash进行读取,所以需要将这个快速编程的代码放置于RAM中运行,以避免对Flash进行命令读取。 那么,大家可能又有疑问了,那为什么STM32L4Cube中并没有使用__RAM_FUNC关键字,STM32L452的Flash是singlebank,难道它就不需要放到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一个行(256Bytes)的数据写到目标地址中,所以也就是说快速编程时,还会去访问源数据,如果源数据放在Flash就会导致问题产生。下面,我们解答一个移植中常见问题。 在从STM32L4到STM32G0的移植中,直接将STM32L4示例代码中定义的源数据的数组代码: /*Tableusedforfastprogramming*/staticconstuint64_tData64_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读取源数据,就导致程序死在快速编程过程。所以,需要将数组修改为: /*Tableusedforfastprogramming*/uint64_tData64_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代码进行快速编程的话,建议看一下参考手册里快速编程的步骤,在步骤中的第一步时使用PageErase对当前页进行擦除后对当前页进行快速编程,每次一页,也就是“擦除当前页→快速编程当前页→擦除下一页→快速编程下一页→……”。 下面来仔细阅读参考手册,关注一下另外几个要点。 第四要点:关于时钟,在快速编程的过程中,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编程代码。 |