和启动代码卯了五天终于搞明白DAVE集成环境下启动代码是怎么修改sp值的了。
网上全是keil MDK集成环境的启动代码分析,这英飞凌太坑了。。。。。。,
言归正传:
英飞凌XMC4400单片机的ROM固化引导程序中将SP的值赋为0x2000Fyyy(记不清了,用yyy代替),而进入main()后SP的值变为0x1FFFC800。这一过程是这样实现的:
Startup文件夹中有 startup_XMC4400.S这样一个汇编启动文件,其中有如下代码:
/* Reset Handler */
.thumb_func
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp,=__initial_sp
#ifndef __SKIP_SYSTEM_INIT
ldr r0, =SystemInit
blx r0
#endif
标红句是经ROM固化引导程序后执行的第一条指令,其将SP的值设置为__initial_sp,__initial_sp是一个可被其它文件代码修改或赋值的符号,苦苦寻找了五天后(使用搜索工具无法搜到),终于在连接脚本文件linker_script.ld中找到了它,见如下脚本:
/* DSRAM layout (Lowest to highest)*/
Stack (NOLOAD) :
{
__stack_start = .;
. = . + stack_size;
__stack_end = .;
__initial_sp = .;
} > SRAM_combined
该连接脚本__initial_sp = .;这句话的意思是将当前计数器的数值付给符号__initial_sp,而当前计数器的数值为SRAM_combined首地址加上堆栈的大小。接脚本文件linker_script.ld的开始部分定义了SRAM_combined和stack_size,见如脚本:
MEMORY
{
FLASH_1_cached(RX) : ORIGIN = 0x08000000, LENGTH = 0x80000
FLASH_1_uncached(RX) : ORIGIN = 0x0C000000, LENGTH = 0x80000
PSRAM_1(!RX) : ORIGIN = 0x1FFFC000, LENGTH = 0x4000
DSRAM_1_system(!RX) : ORIGIN = 0x20000000, LENGTH = 0x8000
DSRAM_2_comm(!RX) : ORIGIN = 0x20008000, LENGTH = 0x8000
SRAM_combined(!RX) : ORIGIN = 0x1FFFC000, LENGTH = 0x14000
}
stack_size = DEFINED(stack_size) ? stack_size : 2048;
故在标红处修改数值即可修改SP的栈顶和预置大小了。注意SRAM_combined还用于了其它存储区的分配,故修改SP的预置大小来修改栈顶比较妥当。
当然我修改SP栈顶的目的是为了使用MPU硬件来设置栈溢出陷阱,保证程序的鲁棒性。作了如下修改:
{
__stack_start = .;
. = . + stack_size;
__stack_end = .;
__initial_sp = . - 32;
} > SRAM_combined
将栈顶前移32个字节,使用MPU将这32个直接设为不可访问。