STM32启动文件中的符号研究:__Vectors、__Vectors_End

STM32的启动文件中,包含了一些可被外部调用的变量,如__Vectors、__Vectors_End等:

; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size

__Vectors       DCD     __initial_sp               ; Top of Stack

...

                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
__Vectors_End
__Vectors_Size  EQU  __Vectors_End - __Vectors

在某些特定场景下,这些变量会很有用,比如确定向量表大小。对于这些符号的含义,网上可以找到一些说明,但是其作用机理,没多少人提及。当然也许是懂汇编的人一眼就能看出,不屑于写出说明。

我们在某个c文件中做如下调用:

extern uint32_t __Vectors;
extern uint32_t __Vectors_End;
extern uint32_t __DEVICE_INFO;

uint32_t *pVectors;
uint32_t *pVectorsEnd;
volatile uint32_t VectorsSize;

void asmVectorDemo(void)
{
    pVectors = &__Vectors;
    pVectorsEnd = &__Vectors_End;
    VectorsSize = (uint32_t)pVectorsEnd - (uint32_t)pVectors;
}

调试观察,可以发现各个变量的真实数值:

__Vectors = 0x20003608  //这个值实际上是__initial_sp的地址,&__initial_sp可以获取到
__Vectors_End = 0x200013A4//
VectorsSize = 0x000000EC

pVectors = 0x08000000 &__Vectors
pVectorsEnd = 0x080000EC &__Vectors_End

由此可以初步得出结论:
汇编文件中DCD分配一个4字节空间,并将变量的地址(取指针)保存下来。对应的标号值就是该指针

这样,就可以方便地在汇编文件中添加一些固有信息,用于标记固件的版本、编译日期等。举例如下,先在c文件中添加变量:

extern uint32_t __Device_Info;
char * deviceInfo = "this is a demo string";
char * pDeviceInfo;

void asmVectorDemo(void)
{
    ...
    pDeviceInfo = (char*)(*(uint32_t*)__DEVICE_INFO);
}

再修改汇编文件:


                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
                EXPORT  __Device_Info
                IMPORT  deviceInfo
__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     __Device_Info              ; Reserved
                DCD     0                          ; Reserved

...

                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
__Vectors_End
__Vectors_Size  EQU  __Vectors_End - __Vectors
    
__Device_Info   DCD     deviceInfo

调试观察,可以看到:

__Device_Info=0x200013A4
deviceInfo = 0x0800A728 "this is a demo string"
&deviceInfo = 0x200013A4 &deviceInfo
*(uint32_t*)__Device_Info=0x0800A728
pDeviceInfo=0x0800A728 "this is a demo string"

通过对汇编文件中变量的多次寻址、变换,得到了在c文件中定义的变量的内容。

这样做的主要价值,是在做Bootloader启动时、IAP升级时,对升级固件的合法性做全面的校验。Bootloader启动时,并不能直接获取新固件中由C文件定义的变量的地址、内容,而对于特定的cortex-m系列单片机,其启动文件格式的固定的,我们在固定偏移地址0x20处填充了“deviceInfo”的地址,就可以根据这个地址去计算偏移量,从而找到真正的deviceInfo在新固件中的存储位置。

你可能感兴趣的:(嵌入式软件,MCU及外设驱动)