iap跳转的作用:使用boot作为app升级,通常使用串口ymodem协议进行更新app,boot一般是占用很小的flash
大约可以设置16kb,然后设置app的地址,设置相对的偏移地址后跳转到app
ymodem协议:bootloader使用完善ymodem协议(优化完善stm的ymodem协议),以及xshell终端结束(超详细教程,简单好学,看了秒懂)_IT嵌入式小生-优快云博客
几个注意的点:
1.关闭中断之后,进入app要开启中断
2.看门狗被开启之后,将永远不会被关闭,所以要做好喂狗的处理
3.一般存在设置向量表的函数,跳转之后要设置相关的向量表,否则就会导致中断无法开启
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
4.如果使用分散加载文件,一定要修改分散加载文件的起始地址,否则就会找不到中断向量表,无法开启中断
/* 函数指针重命名 主要是用于跳转 */
typedef void (*pFunction)(void);
/* app起始执行地址 */
#define APPLICATION_ADDRESS (uint32_t)0x08004000
/* 跳转函数 */
pFunction Jump_To_Application;
/* 跳转地址,中间变量作用 */
uint32_t JumpAddress;
/* 主流STM32芯片的SRAM地址范围都是从 0x2000 0000处开始。 128 Kbytes 的 SRAM
28 Kbytes的SRAM 地址范围是 0x2000 0000 --0x2001 FFFF;
所以 SP & 0x2FFE 0000 == 0x2000 0000,意味着如果超出128sram 就肯定是不正确的,所以检查17之后的位
同理,不同大小的sram 0x2FFE0000是需要改变的
*/
/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* 跳转到程序运行地址 */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
/* 转换为函数类型 */
Jump_To_Application = (pFunction) JumpAddress;
/* 关闭中断 这个非常重要,如果没有关闭boot下的中断,很容易跳到app后被卡死*/
__disable_irq();
/* 初始化app栈指针 */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
禁用开启中断的方式:
第一种
__set_PRIMASK(0) /* 使能全局中断 */
__set_PRIMASK(1) /* 禁止全局中断*/
第二种
__enable_irq(); /* 使能全局中断 */
__disable_irq(); /* 禁止全局中断*/
注意:
__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发
中断发生后,相应的寄存器会将中断标志置位,由于相应的中断标志没有清空,因而还会触发中断。所以要想禁止所有中断,必须对逐个模块的中断进行Disable操作,由于每个模块中断源有很多,对逐个中断Disable的话比较复杂,较为简单的方法是通过XXX_ClearITPendingBit()清除中断标志或者直接通过XXX_DeInit()来清除寄存器的状态。这样在__enable_irq()开启总中断后,MCU就不会响应之前触发的中断了。
第三种方法:操作BASEPRI寄存器,屏蔽所有比该优先级底的中断
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)