STM32+HAL库 自定义BootLoader编程 单APP 最简实现方法 📅 2026/8/9 9:21:29 自定义BootLoader编程一、FlashFlash物理分区页Page扇区Sector块Block。STM32H7片上FlashSTM32H74x外设手册上写到有两个bank每个bank为1M每个sector为128kb最小按sector擦除。支持16位、32位、64位读取。写入为32字节写入不足时先将原有数据读到缓冲区将要写入的数据替换到缓冲区中再将缓冲区数据写入自动完成。分区规划2Mb大小即2048KbFlash范围为0x0800 0000~0x081F FFFF。规划Boot分区128KbAPP1分区896KbAPP2分区896KbConfig区128Kb。分区大小地址Boot128K0x0800 0000~0x0801 FFFFAPP1896k0x0802 0000~0x080F FFFFAPP2896k0x0810 0000~0x081D FFFFConfig128K0x081E 0000~0x081F FFFF二、Cortex内核寄存器组R13堆栈指针(SP - Stack Pointer)SP有两个MSPMain Stack Pointe和PSPProcess Stack Pointer无RTOS时只使用MSP。R14链接寄存器 (LR - Link Register)当执行子函数时LR中保存着下一条指令的地址子函数执行完成后告诉CPU该回哪里继续执行主程序。当执行中断服务函数时LR 里存的是一个特殊值如0xFFFFFFF9。这个值告诉CPU中断结束后返回线程模式还是处理模式。R15程序计数器 (PC - Program Counter)指向当前正在执行的指令地址总结这套体系分为子函数处理和中断服务两个部分中断服务中断发生时硬件自动压栈到SP中中断服务完成后硬件出栈LR决定了返回线程模式还是处理模式PC决定了要CPU重新回到哪个位置继续执行程序子函数调用编译器PUSH到SP中调用完成后编译器POP通过LR回到被打断的主程序位置中断向量表与Cortex复位运行流程中断向量表有256个后面的为外设的中断了不关心。中断向量表的首地址位于程序所占据的Flash空间的首地址这里的每一个向量都是32bits的也就是4个字节中断向量表的第一个存放着复位待写出的MSP值第二个为复位向量存放着复位待写出的PC值。程序复位运行以后将中断向量表中的__initial_sp赋给MSP寄存器以告诉cpu栈顶位置在哪将Reset_Handler赋给PC寄存器用来告诉cpu从哪开始执行程序中断向量表、MSP寄存器、初始栈顶值辨析中断向量表前两个存放着复位待写入的MSP、PC值复位后将中断向量表MSP值写入到MSP寄存器中中断向量表MSP值存放的是初始栈顶值。三、STM32STM上电到运行的流程对于boot和app来说可以视为两套系统在自定义BootLoader到APP1转换的过程中需要配置好这3项步骤如下获取APP1的初始MSP栈顶值。获取APP1的初始PC值。将Boot向量表重定义到APP1的向量表。Keil代码实现BOOT位于0x0800 0000~0x0801 FFFFAPP1位于0x0802 0000~0x080F FFFF。1.先宏定义分块的起始地址方便后续修改2.获取APP1的初始MSP栈顶值这里解释一下APP1_START_ADDRESS是APP1的首地址这个地址存放着初始MSP值目前只是一个数需要使用(volatileuint32_t*)将其转化为指针同时告诉编译器不要优化它最终通过*解引用拿到其中的栈顶值。3.接下来获取APP1的初始PC值4.设置向量表到APP1的向量表从而从BOOT切换到APP1程序后APP1程序发生中断时知道去哪调用中断函数。5.在这3步的前后禁用与打开中断__disable_irq();__enable_irq();6.最终使用跳转命令((void(*)(void))app1ResetHandler)();//标准的C语言语法技巧用于将任意地址数值强制转换为函数并执行跳转跳转程序全貌如下Keil烧写设置分别为全片擦除2M、擦除对应sector128kb、不擦除。编程、校验、复位运行。其中擦除sector需要修改IROM1使用这样可以做到只对对应扇区sector的编程。Bott程序的IROM1设置为APP程序设置为这里没有使用HAL函数可能标准库也能用