【STM32】IAP升级02关闭总中断,检测栈顶指针

本文介绍了IAP升级过程中的中断管理技巧,包括如何正确禁用和启用总中断,以及在升级前后检测栈顶指针以确保程序正确运行。特别提到需对每个中断模块单独处理以防止遗留中断,以及在Bootloader和APP切换时对栈空间的检查方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IAP升级方法

IAP升级时需要关闭总中断

TM32在使用时有时需要禁用全局中断,比如MCU在升级过程中需禁用外部中断,防止升级过程中外部中断触发导致升级失败。

ARM MDK中提供了如下两个接口来禁用和开启总中断:

__disable_irq(); // 关闭总中断

__enable_irq(); // 开启总中断 但测试发现这样一个问题,在关闭总中断后,如果有中断触发,虽然此时不会引发中断,但在调用__enable_irq()开启总中断后,MCU会立即处理之前触发的中断。

这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断标志没有清空,因而还会触发中断。

所以要想禁止所有中断,必须对逐个模块的中断进行 Disable操作,由于每个模块中断源有很多,对逐个中断Disable的话比较复杂,较为简单的方法是通过 XXX_ClearITPendingBit()清除中断标志或者直接通过XXX_DeInit()来清除寄存器的状态。这样在 __enable_irq()开启总中断后,MCU就不会响应之前触发的中断了。

检测栈顶指针

bootloader跳跃到APP程序的时候,会进行栈顶指针的检测,栈顶指针也就是我们程序能够运行的最大空间

if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)//检测栈顶指针
    { 
      /* Jump to user application */
      /*ApplicationAddress为用户程序的栈地址,+4便为用户程序的复位中断向量地址*/  
      JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) ApplicationAddress);
      /*执行用户空间的复位中断向量函数,里面主要是进行系统时钟配置,执行用户空间的main函数数*/  
      Jump_To_Application();
    }

在保存了一个完整的 APP 到了对应的位置后,我们需要对栈顶进行检查操作,初步检查程序设置正确再进行跳转。我们以 Flash APP 为例,用 bin 文件查看工具。可以看到 bin 的内容默认为小端结构
在这里插入图片描述
0x2000 0818就是栈顶指针
0x0801 0289是app的Reset_Handler函数地址

程序在运行过程中,0x20000000是我们SRAM运行的起始地址,空间是128KB,也就是0x20000000-0X2001FFFF这个范围。 所以*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) ,这句话的意思是取得用户地址空间存放的数据,这个空间就是0x08010000,当APP运行的程序栈顶指针落在SRAM区域时,也就是0x20000000到0X2001FFFF这个区间时候,这个时候即是有效的栈顶指针,由于开始的地址是0x20000000,而结束的地址是0X2001FFFF,我们只要判断它的高16位,即是确定这个地址范围在从0x2000开始。

<think>好的,用户想了解如何实现STM32IAP在线升级功能。我需要根据提供的引用内容来整理回答。首先,用户提到的引用1到4都是关于STM32IAP升级的,特别是引用4详细描述了原理和步骤。 首先,我应该解释IAP的基本概念,对比ISP,说明为什么需要IAP。引用1提到IAP和ISP的区别,这里可以简要说明。然后,根据引用4,IAP的实现需要两部分:BootLoader和APP程序。需要分步骤说明,比如Flash地址划分、BootLoader设计、通信协议、APP跳转等。 接下来,可能需要提到示例代码的存在,引用2和3提供了示例代码和上位机工具的信息,应该提到这些资源。另外,注意事项部分也很重要,比如中断向量表偏移、Flash擦除注意事项、校验机制,这些在引用4中都有涉及。 用户的问题还包括实现方法和示例代码,所以需要给出具体的步骤,比如如何设置工程,如何配置中断向量表,跳转的代码示例。同时,确保使用正确的LaTeX格式,比如Flash地址用$0x08000000$这样的格式。 还要考虑用户可能的后续问题,比如如何验证升级是否成功,或者如何处理通信中的错误,但根据引用内容,可能需要集中在现有的步骤上。最后生成相关问题,比如IAP与ISP的区别,中断处理,通信协议选择,校验方法等。 需要检查是否符合用户的要求,结构是否清晰,步骤是否详细,并且引用正确。确保使用中文,代码部分用正确格式,数学表达式用$符号包裹。</think>### STM32 IAP在线升级实现详解 #### 一、IAP基本原理 IAP(In Application Programming)允许通过应用程序自身对Flash存储器进行编程,无需专用烧录工具。与需要硬件引脚控制的ISP不同,IAP可实现远程在线升级[^1][^4]。核心实现步骤如下: $$Flash\ 地址划分 = \begin{cases} BootLoader区 & 0x08000000-0x0800FFFF \\ APP程序区 & 0x08010000-0x0807FFFF \end{cases}$$ #### 二、实现步骤 1. **存储器分区** - BootLoader占用$16KB$($0x08000000-0x0800FFFF$) - APP程序从$0x08010000$开始存放 - 通过Keil工程配置实现: ```c #define APP_ADDRESS 0x08010000 ``` 2. **BootLoader设计** ```c void jump_to_app(uint32_t app_addr) { typedef void (*pFunction)(void); pFunction Jump_To_Application; if((*(__IO uint32_t*)app_addr) & 0x2FFE0000) == 0x20000000) { // 检查地址 Jump_To_Application = (pFunction)(*(__IO uint32_t*)(app_addr + 4)); __set_MSP(*(__IO uint32_t*)app_addr); // 设置主堆指针 Jump_To_Application(); // 跳转到APP } } ``` 3. **APP工程配置** - 修改中断向量表偏移: ```c SCB->VTOR = FLASH_BASE | 0x10000; // 偏移量=0x10000 ``` - 设置Keil的ROM起始地址为$0x08010000$ 4. **通信协议实现** - 使用YModem协议传输BIN文件 - 关键数据结构: ```c typedef struct { uint8_t header; // 起始字节(0x01/0x04) uint8_t packetNum; // 包序号 uint8_t packetCmp; // 包序号补码 uint8_t data[1024]; // 数据区 uint16_t crc16; // 校验码 } YModem_Packet; ``` #### 三、开发资源 1. 官方示例代码参考STM32CubeH7软件包的IAP例程[^2] 2. 开源上位机工具推荐使用STM32CubeProgrammer配套工具 3. 完整工程需包含Flash擦除/写入驱动(参考引用4的FLASH_If_Erase()函数) #### 四、注意事项 1. 中断向量表必须按$0x200$对齐(STM32L4系列要求) 2. Flash擦除前必须关闭所有中断 3. 推荐增加CRC32校验机制,错误率可降低至$10^{-6}$[^3] 4. 使用双Bank Flash的型号(如STM32F76xxx)可实现无感升级
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值