[STM32F4] STM32F4系列的app和boot相互跳转

[复制链接]
2868|11
 楼主| 慢动作 发表于 2023-7-28 00:34 | 显示全部楼层 |阅读模式
首先要明确的是ISP和IAP两个概念。

     ISP 即(In-System Programming)在系统可编程,指电路板上的空白器件可以编程写入最终用户代码, 而不需要从电路板上取下器件,已经编程的器件也可以用ISP 方式擦除或再编程。

     IAP:In Application Programming 是指在应用编程,即在程序运行中编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。

   STM32F4芯片自带ISP程序,在系统存储区内,通过开机的时检测BOOT0和BOOT1的引脚电平来判断从什么地方启动,如下图
1055464c29c9f001c0.png

 楼主| 慢动作 发表于 2023-7-28 00:35 | 显示全部楼层
当BOOT1处于低电平,同时BOOT0是高电平时,系统从System memory启动,这里保存着stm32出厂时内置的ISP程序,可以通过串口或者usb口等来进行内置flash的编程,这部分原理数据手册里写的很清楚。

7549764c29cb3b7d82.png
 楼主| 慢动作 发表于 2023-7-28 00:35 | 显示全部楼层
ISP这部分由官方实现,是一段固化的程序,使用isp软件进行升级即可,下面我们来看一下IAP的问题。



IAP:

      IAP的好处就是不用进行跳线改变boot引脚的电平,就可以进行在线编程,在产品化以后使用的比较多,通常用一个boot程序来引导,选择是进行升级还是进入app应用中。这一部分,st官方也有示例代码(多么贴心)。
 楼主| 慢动作 发表于 2023-7-28 00:35 | 显示全部楼层
官方给出的IAP的核心代码:
  1. #define     __IO    volatile
  2. typedef  void (*pFunction)(void);
  3. #define APPLICATION_ADDRESS   (uint32_t)0x08000000
  4. pFunction Jump_To_Application;
  5. uint32_t JumpAddress;
 楼主| 慢动作 发表于 2023-7-28 00:35 | 显示全部楼层
  1.     /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
  2.     if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
  3.     {
  4.       /* Jump to user application */
  5.       JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
  6.       Jump_To_Application = (pFunction) JumpAddress;
  7.       /* Initialize user application's Stack Pointer */
  8.       __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
  9.       Jump_To_Application();
  10.     }
 楼主| 慢动作 发表于 2023-7-28 00:35 | 显示全部楼层
  1.if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)  这句旨在判定 APPLICATION_ADDRESS这个地址保存的是否是SP堆栈指针,下面是stm32的矢量表:
5470564c29ce1b5289.png
 楼主| 慢动作 发表于 2023-7-28 00:35 | 显示全部楼层
从这个表中能看出来,用户应用的首4个字节应该放的是栈顶的值,启动采样完boot引脚后,CPU 将从地址 0x0000 0000 获取栈顶值,然后从始于 0x0000 0004 的自举存储器开始执行代码。stm32的ram空间地址范围是0x20000000~0x2001ffff,共128K(42x和43x的ram空间更大,但是我们使用前128K进行判断足够了),所以使用这句来判断栈顶指针是否合法。
 楼主| 慢动作 发表于 2023-7-28 00:36 | 显示全部楼层
2.APPLICATION_ADDRESS保存的是用户程序的首地址,所以*(__IO uint32_t*) (APPLICATION_ADDRESS + 4)就是用户程序空间复位向量的地址
 楼主| 慢动作 发表于 2023-7-28 00:36 | 显示全部楼层
3.Jump_To_Application = (pFunction) JumpAddress;Jump_To_Application是一个函数指针,这句话将函数指针指向复位函数。
 楼主| 慢动作 发表于 2023-7-28 00:36 | 显示全部楼层
4.__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);设置堆栈指针sp,指向用户代码的首地址。
 楼主| 慢动作 发表于 2023-7-28 00:36 | 显示全部楼层
5.Jump_To_Application();跳转到用户程序,把函数指针赋值给pc指针。
 楼主| 慢动作 发表于 2023-7-28 00:36 | 显示全部楼层
stm32程序跳转总结:1.要赋值有效的sp栈顶指针  2.要给pc指针赋值 3.应用程序要修改中断向量表的偏移地址

   从这个结论,我们可以实现从boot到app的跳转,同样的原理也可以从app跳转到boot程序,也是使用相同的代码。

程序间跳转的时候,如果使能了某项外设,一定要在跳转前使用xxx_DeInit 库函数关闭一下,外设才能在两段程序中都正常使用。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

82

主题

1071

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部