flash脚本改装(STM32只下载程序到RAM中并运行测试-NO_FLASH)_重复

搞嵌入式的知道,NORFLASH,可以掉电保存数据,但是反复擦写比较容易坏,在开发阶段必然会不停的烧写和验证,这个过程必不可少,这必然会引入损坏norflash的风险。其实这也不是不可以规避的风险,比如开发阶段把程序下载到RAM中并运行,就...

搞嵌入式的知道,NORFLASH,可以掉电保存数据,但是反复擦写比较容易坏,在开发阶段必然会不停的烧写和验证,这个过程必不可少,这必然会引入损坏norflash的风险。其实这也不是不可以规避的风险,比如开发阶段把程序下载到RAM中并运行,就可以规避这个。缺点就是掉电没法保存数据,不过RAM通常会比NorFLASH空间小,等程序的验证完了,稍作修改就可以下载到norflash中了,这样最小次数的烧写到flash中。

之前写个一篇文章(STM32启动代码分析及stm32启动代码实现|C语言)写道,cortext-m4的启动过程:

flash脚本改装(STM32只下载程序到RAM中并运行测试-NO_FLASH)_重复

1,在系统reset时会去找异常向量表中前4个字节指向的地址作为栈顶

2,第4-8个字节是resethandler函数的地址,然后PC会load这个地址,并运行。这个reset向量指向的函数是我们能写代码控制的最开始的位置。cortext-m4从向量表中把reset异常的函数地址加载到PC寄存器并运行是纯硬件行为,而且是无法更改的,那么如何做到从RAM运行了,就需要解决:

1,默认的向量表是在NorFlash最开始的位置,现在就需要修改向量表到RAM中。

2,如何让PC寄存器从RAM中向量表开始加载reset_handler函数地址。---显然我们是没法用软件控制的,我们的软件的第一行代码都跑不到。

一个个的搞。

STM32只下载程序到RAM中并运行测试-NO_FLASH

STM32只下载程序到RAM中并运行测试-NO_FLASH

如图片把向量表,和指令text段都放在了RAM地址空间中,所以解决第一个问题主要是修改连接脚本。把原先从FLASH加载改到RAM加载,这时在coretx-m4眼里已经没有了nor_flash。

另外就是data段把LMA和VMA都放在RAM中了。(原来在FLASH中运行时,是需要把data段数据从flash中复制到RAM中,就是两份data段的数据了,现在就不需要这个复制过程了)

连接脚本改了后:

arm-none-eabi-nm工具看一下

STM32只下载程序到RAM中并运行测试-NO_FLASH

RAM中地址是0x20000000开始的,对比flash地址0x08000000。cortext-m4眼中的VMA已经全部是在RAM中,还有一个问题就是cortext-m4怎么知道向量表在RAM中了。

直接看图片抓重点,有个VTOR寄存器可以更改向量表的位置。

STM32只下载程序到RAM中并运行测试-NO_FLASH

STM32只下载程序到RAM中并运行测试-NO_FLASH

直接指定VTOR为RAM开始的地方

STM32只下载程序到RAM中并运行测试-NO_FLASH

,其实我的程序现在还比较小,也没其他的中断,可以不指定这个,但是你一当把程序下载到ram中,在按复位按钮,或者产生其他的异常及中断,因为没指定VTOR,程序肯定跑飞。还是加上了

2,第二个问题,更改PC到新的reset_handler函数出怎么解决了。首先这个你是没法通过改自己的编写的代码去做到的,因为跑不到你的第一行代码那儿去。我的调试环境一直都是openocd+gdb。

先是下载到ram中。

STM32只下载程序到RAM中并运行测试-NO_FLASH

看一下RAM和编译的程序,没问题。

STM32只下载程序到RAM中并运行测试-NO_FLASH

dump来看reset是调用函数地址是0x2000006b

这个CPU目前最初始的状态

STM32只下载程序到RAM中并运行测试-NO_FLASH

其实到这里就可以让CPU直接跳到0x2000006b处就行。

STM32只下载程序到RAM中并运行测试-NO_FLASH

STM32只下载程序到RAM中并运行测试-NO_FLASH

程序也是正常的跑起来了,但是我们写代码是肯定不知道reset异常对应handler函数在哪位置了。

现在是0x2000006b,如果这个文件前面加个一些函数就可能0x2000008b了反正不能确定编译器把它放在哪里?

都到这地方了,就是函数地址不固定了,那就固定他就好了,最好的是把它固定在向量表紧接着的位置。

STM32只下载程序到RAM中并运行测试-NO_FLASH

向量表最后一个位置是0x000001A8.紧接着它的位置就是0x200001AC改一下代码及脚本。

STM32只下载程序到RAM中并运行测试-NO_FLASH

把这个reset_handler放到.reset_fun段中。

STM32只下载程序到RAM中并运行测试-NO_FLASH

然后连接脚本加上这段,并且把VMA放到0x200001AC位置。

STM32只下载程序到RAM中并运行测试-NO_FLASH

好了地址固定了,最后VScode也好,还是命令行调试,最后就一句话写到脚本里

openocd.exe-fF:\OpenOCD-20200729-0.10.0\share\openocd\scripts\interface\stlink-v2-1.cfg-fF:\OpenOCD-20200729-0.10.0\share\openocd\scripts\target\stm32l4x.cfg-cinit-c"resethalt"-c"load_imagehello.bin0x20000000"-c"resume0x200001AC"

下载及运行都成功。

代码路径https://gitee.com/android_life/stm32_freertos_opensource/tree/master/assembly/run_code_on_ram

前面说了这个

原来在FLASH中运行时,是需要把data段数据从flash中复制到RAM中,就是两份data段的数据了,现在就不需要这个复制过程了

为啥要复制了?欢迎留言