目录
Preface:
(一)STM32上电启动流程
(二)BootLoader相关
(三)Clion配置
Preface:
有关STM32的BootLoader主要还是参考了许多大佬的文章,这里只是简单地列举一下,做一个总结,方便日后用到的时候能够快速找到。
(一)STM32上电启动流程
这篇文章讲得很详细了,这里做一个个人总结:
cortex-m系列中,中断向量表存放在 Flash 开始部分,Flash中第一个字存放栈顶指针,第二个字存放复位中断服务函数入口地址,其他中断服务函数入口地址依次存放在Flash中。STM32上电的时候首先会自动去读取flash的第一个字,并赋给MSP(主栈顶指针),然后读取第二个字,并赋给PC(程序计数器);而因为PC存放的是下一个要执行的指令,所以接下来就会跳转到复位中断服务函数中执行;
此外,因为内核默认读的是0x0000 0000处的内容,而STM32的Flash地址被设置到了0x0800 0000,因此TM32内部自动将地址0x0800 0000开始的内容重映射到首地址0x0000 0000中,这样就解决了从0x0000 0000读取中断向量表的问题。
然后,复位中断服务函数中调用了SystemInit()函数,该函数主要作用是设置中断向量表的偏移地址(VOTR寄存器)。也就是说中断向量表位置是可变的,当使用BOOT后,就需要在APP修改该偏移地址。执行完SystemInit()函数后,就会跳转到__main()函数,注意这个__main()和平时说的main()并不一样,如下图所示,__main()执行的是左边的过程,执行完毕之后才会跳转到我们熟悉的main()函数(图片及内容参考自大佬:不咸不要钱的文章):
(二)BootLoader相关
首先,这里主要参考了这几篇文章,结合在一起看一遍就会非常清晰了(感谢各位大佬):
- STM32单片机bootloader扫盲
- STM32固件升级详解(BootLoader)
- 【STM32】制作一个bootloader
- 【嵌入式实战】STM32 Bootloader 快速实现(超详细)
bootloader本质上也是一个app程序,只不过它具备跳转到用户app,以及接收外部数据更新用户app的功能;
而MCU上电后,主要就是先去取第一个字赋给MSP,然后取第二个字赋给PC,接下来就执行复位中断服务函数(第二个字就是该函数的入口地址);在复位中断服务函数中设置中断向量表的偏移地址,准备C环境,最后跳转到main()函数。同理,从bootloader跳到APP也需要干这两件事情,只不过上电时是单片机自动加载的MSP和PC,而从bootloader跳到APP则需要我们编写函数进行跳转。
也就是说,我如果想实现bootloader,就要搞两个工程,并将代码下载到flash中的不同区域:
一个是bootloader工程,下载到上电起始执行位置;当MCU上电时跟之前大体上一样,首先读取第一个字赋给MSP,然后读取第二个字赋给PC,接下来执行PC中的内容,但此时PC中的内容不再是普通的复位中断服务函数,而是下载进去的bootloader中的跳转函数,在跳转函数中判断是否需要升级(OTA,Over-The-Air,也就是远程更新app程序),如果需要升级,则先下载新的程序进flash中的另外一片区域暂存(就是OTA DATA区),防止升级失败导致系统一直在bootloader中,下载完成之后进行数据校验,无误后才擦除原app程序,并将OAT DATA区的内容copy到app区,再擦除升级指令(因为已经升级完毕了),最后重启系统,完成远程升级。
另外一个则是用户app工程,该工程要下载到某一片区域,而且需要知道区域的起始地址,因为bootloader需要跳到此处;此外注意还需要在system中修改app工程下系统的中断向量表的偏移地址,修改为该程序的起始地址+4字节(一个字的偏移);因为bootloader跳到此处后,第一个字将赋给MSP,第二个字就是app程序的复位中断服务函数了,就类似于app程序复位了一样;如果没有修改中断向量表的偏移的话,默认就跳转到了0x0000 0000+4字节(一个字)处了,将会导致app程序无法执行。
(三)Clion配置
以前用Keil比较多,修改下载地址在魔法棒那里的Target就能修改了;而现在主要用Clion,需要做一点修改,下面记录一下如何修改:
首先找到工程中的xxx_FLASH.ld文件,找到FLASH大小的一行,如下所示:
编译后,找到cmake中的.map文件,搜索FLASH,发现与ld文件中的一致;
接下来修改.ld文件中的值,设定为需要下载到的起始地址,比如说0x0800 1000,再对CmakeLists.txt选择从cubemx中更新工程,再编译,就会发现.map文件中就是刚刚设置的flash起始地址,大功告成!
完~
以上均为个人学习心得,如有错误,请不吝赐教~
THE END