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

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

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

#define STM32_APP_BASE		0x08020000		// APP flash start address

void iap_jumpapp(void)
{
    // 检查栈顶是否合法,,确保栈顶落在0x24000000-0x24FFFFFF 之间,刚好在stm32h7的RAM范围内
	if (((*(uint32_t*)(STM32_APP_BASE)) & 0xff000000 ) == 0x24000000 ) {
        
        // 检查reset入口是否正确
		if (((*(uint32_t*)(STM32_APP_BASE + 4)) & 0x0fff0000 ) == 0x08020000 ) {

			JumpToApp = (pfunction)((*(uint32_t*)(STM32_APP_BASE + 4)));
			MSR_MSP(*(uint32_t*)STM32_APP_BASE);

			JumpToApp();
		}
	} else {
		...
	}
}

栈顶地址 和 reset入口地址具体是什么???

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

__Vectors       DCD     __initial_sp                      ; Top of Stack
                DCD     Reset_Handler                     ; Reset Handler
                DCD     NMI_Handler                       ; NMI Handler
                DCD     HardFault_Handler                 ; Hard Fault Handler
                DCD     MemManage_Handler                 ; MPU Fault Handler
                DCD     BusFault_Handler                  ; Bus Fault Handler
                DCD     UsageFault_Handler                ; Usage Fault Handler
                DCD     0                                 ; Reserved
                DCD     0                                 ; Reserved
                DCD     0                                 ; Reserved
代码 说明 备注
__initial_sp 栈顶地址 程序占用的最大RAM地址,占用RAM大小=RW-data + ZI-data
Reset_Handler reset入口 程序上电后,第一个运行的函数地址

结合map文件和bin文件进行分析

  • 生成map文件中,__initial_sp = 0x2400f2a8
    ...
    HEAP                                     0x2400c2a8   Section     4096  startup_stm32h743xx.o(HEAP)
    Heap_Mem                                 0x2400c2a8   Data        4096  startup_stm32h743xx.o(HEAP)
    STACK                                    0x2400d2a8   Section     8192  startup_stm32h743xx.o(STACK)
    Stack_Mem                                0x2400d2a8   Data        8192  startup_stm32h743xx.o(STACK)
    __initial_sp                             0x2400f2a8   Data           0  startup_stm32h743xx.o(STACK)

    Global Symbols
    ...

另外,从中可以看出
堆栈Stack范围 0x2400d2a8 - 0x2400f2a8 占用8K
Heap范围 0x2400c2a8 - 0x2400d2a8 占用4K
和startup_stm32h743xx.s中的定义对应

Stack_Size		EQU     0x2000       ;;0x400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp


;  Heap Configuration
;     Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; 

Heap_Size      EQU     0x1000        ;;0x200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

                PRESERVE8
                THUMB
  • map文件中,Reset_Handler = 0x0802038d
    Reset_Handler                            0x0802038d   Thumb Code     8  startup_stm32h743xx.o(.text)

生成bin文件中
第一个数据 a8 f2 00 24 即 0x2400f2a8 (__initial_sp)
第二个数据 8d 03 02 08 即 0x0802038d (Reset_Handler)

a8 f2 00 24 8d 03 02 08 31 60 02 08 f1 59 02 08
15 60 02 08 25 0f 02 08 89 87 02 08 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 09 65 02 08
41 12 02 08 00 00 00 00 c5 61 02 08 5d 65 02 08
a7 03 02 08 a7 03 02 08 a7 03 02 08 a7 03 02 08
a7 03 02 08 a7 03 02 08 a7 03 02 08 a7 03 02 08
a7 03 02 08 a7 03 02 08 a7 03 02 08 61 0f 02 08
6d 0f 02 08 a7 03 02 08 a7 03 02 08 a7 03 02 08
a7 03 02 08 a7 03 02 08 a7 03 02 08 a7 03 02 08
a7 03 02 08 a7 03 02 08 a7 03 02 08 a7 03 02 08

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

生成bin文件user run命令:
fromelf.exe --bin -o “[email protected]” “#L”


所以

(*(uint32_t*)(STM32_APP_BASE) 即 __initial_sp

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

你可能感兴趣的:(笔记收藏,stm32,bootloader,栈顶地址)