当前位置: 首页 > news >正文

stm32 BootLoader之检查栈顶地址是否合法(否则无法跳转到APP程序)

stm32 BootLoader之检查栈顶地址是否合法

  • Chapter1 stm32 BootLoader之检查栈顶地址是否合法
  • 试验结果
  • 参考文章


正点原子STM32F407 U盘升级程序(IAP)OTA Bootloader APP USB升级+FATFS+USB Host

Chapter1 stm32 BootLoader之检查栈顶地址是否合法

在stm32 IAP例程中,跳转到APP区的时候,都会检查栈顶地址是否合法,以及reset地址是否正确等信息,那么这些判断具体依据什么原理???
以stm32f407ZGT6为例说明

检查栈顶是否合法代码如下:

/**********************************************************************
**** 函数名: jumpToApp()
**** 功  能: 跳转到appa运行程序
**** 参  数:
**** 返回值: 无
**** 时  间: 2025年3月11日
**** 设  计: 
**** 备  注: 
**********************************************************************/
void jumpToApp()
{ 
#if 1// 检查应用程序的栈顶地址是否有效// 应用程序的栈顶地址存储在FLASH_USER_START_ADDR处// 有效栈顶地址的高16位必须是0x2000(即位于SRAM区域)uint32_t app_stack_pointer = *(__IO uint32_t*)FLASH_USER_START_ADDR;printf("应用程序的栈顶地址:0x%08X\n", app_stack_pointer);if ((app_stack_pointer & 0x2FFE0000 ) == 0x20000000)//if (((*(__IO uint32_t*)FLASH_USER_START_ADDR) & 0x2FFE0000 ) == 0x20000000){printf("跳转到应用程序\r\n");// 1. 禁用所有中断__disable_irq(); // 2. 重置和复位时钟HAL_RCC_DeInit(); // 3. 重置所有外设HAL_DeInit(); //复位所有外设// 4. 设置向量表位置SCB->VTOR = FLASH_USER_START_ADDR; //这里可以不用,在APP程序中设置 // 5. 初始化应用程序栈指针// 设置栈指针(MSP)为应用程序的栈顶地址 __set_MSP(*(__IO uint32_t*) FLASH_USER_START_ADDR); //应用程序的栈顶地址存储在FLASH_USER_START_ADDR处// 6. 获取复位处理函数地址JumpAddress = *(__IO uint32_t*) (FLASH_USER_START_ADDR + 4);    // 应用程序的入口地址存储在FLASH_USER_START_ADDR + 4处Jump_To_Application = (pFunction) JumpAddress;                  // 将入口地址转换为函数指针// 7. 跳转到应用程序        Jump_To_Application();                                          // 跳转到应用程序}printf("ADDR != 0x20000000\r\n");     //  栈顶地址无效printf("跳转到应用程序失败!\r\n");
#endif	
}

栈顶地址 和 reset入口地址具体是什么???
从startup_stm32h407xx.s中可以看出,程序第一个地址存放的是__initial_sp,紧接着第二个地址存放的是Reset_Handler;这两个正是所谓的栈顶地址 reset 入口

__Vectors       DCD     __initial_sp               ; Top of StackDCD     Reset_Handler              ; Reset HandlerDCD     NMI_Handler                ; NMI HandlerDCD     HardFault_Handler          ; Hard Fault HandlerDCD     MemManage_Handler          ; MPU Fault HandlerDCD     BusFault_Handler           ; Bus Fault HandlerDCD     UsageFault_Handler         ; Usage Fault HandlerDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     SVC_Handler                ; SVCall HandlerDCD     DebugMon_Handler           ; Debug Monitor HandlerDCD     0                          ; ReservedDCD     PendSV_Handler             ; PendSV HandlerDCD     SysTick_Handler            ; SysTick Handler

在这里插入图片描述
结合map文件和bin文件进行分析
生成map文件中,__initial_sp = 0x20005aa0

    data                                     0x20000000   Data           4  freertos.o(.data)defaultTaskHandle                        0x20000004   Data           4  freertos.o(.data)LEDTaskHandle                            0x20000008   Data           4  freertos.o(.data)HMITaskHandle                            0x2000000c   Data           4  freertos.o(.data)myBinarySem01Handle                      0x20000010   Data           4  freertos.o(.data)uwTickFreq                               0x20000014   Data           1  stm32f4xx_hal.o(.data)uwTickPrio                               0x20000018   Data           4  stm32f4xx_hal.o(.data)uwTick                                   0x2000001c   Data           4  stm32f4xx_hal.o(.data)SystemCoreClock                          0x20000020   Data           4  system_stm32f4xx.o(.data)pxCurrentTCB                             0x20000024   Data           4  tasks.o(.data)__stdout                                 0x200000a4   Data           4  stdout.o(.data)htim7                                    0x200000a8   Data          72  tim.o(.bss)huart1                                   0x200000f0   Data          72  usart.o(.bss)huart2                                   0x20000138   Data          72  usart.o(.bss)htim6                                    0x20000180   Data          72  stm32f4xx_hal_timebase_tim.o(.bss)xQueueRegistry                           0x200001c8   Data          64  queue.o(.bss)__initial_sp                             0x20005aa0   Data           0  startup_stm32f407xx.o(STACK)

另外,从中可以看出
堆栈Stack范围 0x20004aa0 - 0x24005a40 占用4K
ucHeap范围 0x20000e9c - 0x24004a9c 占用15K
和startup_stm32h407xx.s中的定义对应

    .bss                                     0x200007e4   Section     1720  cmsis_os2.o(.bss)Idle_TCB                                 0x200007e4   Data          92  cmsis_os2.o(.bss)Idle_Stack                               0x20000840   Data         512  cmsis_os2.o(.bss)Timer_TCB                                0x20000a40   Data          92  cmsis_os2.o(.bss)Timer_Stack                              0x20000a9c   Data        1024  cmsis_os2.o(.bss).bss                                     0x20000e9c   Section    15360  heap_4.o(.bss)ucHeap                                   0x20000e9c   Data       15360  heap_4.o(.bss)STACK                                    0x20004aa0   Section     4096  startup_stm32f407xx.o(STACK)Global Symbols

map文件中,Reset_Handler = 0x08010261

    PendSV_Handler                           0x080101fd   Thumb Code    88  port.o(.emb_text)vPortGetIPSR                             0x08010259   Thumb Code     6  port.o(.emb_text)Reset_Handler                            0x08010261   Thumb Code     8  startup_stm32f407xx.o(.text)

生成bin文件中,用SEGGAR J-Flash程序打开,查看bin文件
第一个数据 a0 5a 00 20 即 0x20005aa0 (__initial_sp)
第二个数据 61 02 01 08 即 0x08010261 (Reset_Handler)

在这里插入图片描述
在这里插入图片描述

所以跳转的时候,直接跳转到0x08010261地址即可!

#生成bin文件user run命令:
fromelf.exe --bin -o “$L@L.bin” “#L”

所以

(*(uint32_t*)(STM32_APP_BASE)__initial_sp(*(uint32_t*)(STM32_APP_BASE+4) 即 Reset_Handler

试验结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08010000 0x00070000  {    ; load region size_regionER_IROM1 0x08010000 0x00070000  {  ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20000000 0x00020000  {  ; RW data.ANY (+RW +ZI)}RW_IRAM2 0x10000000 0x00010000  {.ANY (+RW +ZI)}
}

参考文章

stm32 BootLoader之检查栈顶地址是否合法

http://www.dtcms.com/a/395916.html

相关文章:

  • PyTorch 神经网络工具箱学习总结
  • 容器化 Spring Boot 应用程序
  • python 打包单个文件
  • Python自学21 - Python处理图像
  • 比特浏览器的IP适配性
  • LLHTTP测试
  • 2. 基于IniRealm的方式
  • 第三十四天:矩阵转置
  • MySQL执行计划:如何发现隐藏的性能瓶颈?
  • embedding多模态模型
  • ⚡ GitHub 热榜速报 | 2025 年 09 月 第 3 周
  • Synchronized的实现原理:深入理解Java线程同步机制
  • 初识C++、其中的引用、类(class)和结构体(struct)
  • Qt之常用控件之QWidget(四)
  • Pod生命周期
  • 【课堂笔记】复变函数-3
  • 深度学习-自然语言处理-序列模型与文本预处理
  • 【C语言】迭代与递归:两种阶乘实现方式的深度分析
  • CLIP多模态模型
  • 快手前端三面(准备一)
  • 前端-JS基础-day1
  • 【开题答辩全过程】以 J2EE在电信行业的应用研究为例,包含答辩的问题和答案
  • C++ QT Json数据的解析
  • RAG——动态护栏
  • Spring Boot 全局鉴权认证简单实现方案
  • 【靶场】webshop渗透攻击
  • 深入浅出现代GPU架构:核心类型、精度模式与选择
  • 开发避坑指南(53):git 命令行标签维护方法
  • javaEE初阶 网络编程(socket初识)
  • 基于Springboot + vue3实现的实验室研究生信息管理系统