以LM3S9B90为例。Startup.s文件是系统的启动文件,主要包括堆和栈的初始化配置、中断向量表的配置以及将程序引导到main( )函数等。
Startup.s主要完成三个工作:栈和堆的初始化、定位中断向量表、调用Reset Handler。
a)堆和栈的初始化
Startup.s中的代码如下图所示:
1.程序分别对堆和栈进行了大小的规定以及空间的分配。
Stack EQU 0x00002000 //定义栈的大小。EQU相当于汇编当中的宏定义,Stack替换0x00002000,即8*1024字节=8KB。
Heap EQU 0x00000000 //定义堆的大小。
2.为栈分配8K Byte空间。
AREA STACK, NOINIT, READWRITE, ALIGN=3 //堆栈段, 未初始化, 允许读写, 8字节边界对齐。
说明:AREA命令指示汇编器汇编一个新的代码段或者数据段。Contrx-M3的指令地址要求是字边界对齐(4字节),但是代码段是要求8字节边界对齐的。NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0。
StackMem SPACE Stack //分 配连续 Stack_Size 字节的存储单元并初始化为 0
__initial_sp //标号,代表堆栈顶部地址
3.为堆分配空间。
.
AREA HEAP, NOINIT, READWRITE, ALIGN=3 //堆栈段, 未初始化, 允许读写, 8字节边界对齐。
__heap_base //标号,代表堆末底部地址
HeapMem
SPACE Heap //分配堆空间
__heap_limit //标号,代表堆界限地址
PRESERVE8 //指示编译器8字节对齐。
说明:PRESERVE8 指令指定当前文件保持堆栈八字节对齐。 它设置 PRES8 编译属性以通知链接器。链接器检查要求堆栈八字节对齐的任何代码是否仅由保持堆栈八字节对齐的代码直接或间接地调用。
b)定位中断向量表
;******************************************************************************
;
; Place code into the reset code section.
;
;******************************************************************************
AREA RESET, CODE, READONLY //定义只读数据段,放在CODE区,位于0地址
THUMB //指示编译器以后的指令为THUMB指令
;******************************************************************************
;
; The vector table.
;以下为向量表,在复位时被映射到FLASH的0地址。
;******************************************************************************
EXPORT __Vectors //EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用。EXPORT 命令声明一个符号,可由链接器用于解释各个目标和库文件中的符号引用,相当于声明了一个全局变量。
IMPORT uart0_interrupt //引入UART0中断
IMPORT tick_interrupt //引入systick中断
IMPORT eth_interrupt //引入eth中断
IMPORT timer0_interrupt //引入timer0中断
IMPORT reset_interrupt //引入reset中断
//DCD 命令分配一个或多个字的存储器,在四个字节的边界上对齐,并定义存储器的运行时初值。
__Vectors
DCD StackMem + Stack // ; Top of Stack;栈顶指针,被放在向量表的开始,FLASH的0地址,复位后首先装载栈顶指针
DCD Reset_Handler //; Reset Handler。复位异常,装载完栈顶后,第一个执行的,并且不返回
DCD NmiSR // ; NMI Handler。不可屏蔽中断
DCD FaultISR // ; Hard Fault Handler。硬件错误中断
DCD IntDefaultHandler //; MPU Fault Handler。内存管理错误中断
DCD IntDefaultHandler //; Bus Fault Handler。总线错误中断
DCD IntDefaultHandler //; Usage Fault Handler。用法错误中断
DCD 0 //; Reserved
DCD 0 //; Reserved
DCD 0 //; Reserved
DCD 0 //; Reserved
DCD IntDefaultHandler //; SVCall Handler。系统调用异常,主要是为了调用操作系统内核服务
DCD IntDefaultHandler //; Debug Monitor Handler
DCD 0 // ; Reserved
DCD IntDefaultHandler //; PendSV Handler
DCD tick_interrupt //; SysTick Handler
DCD IntDefaultHandler // ; GPIO Port A
DCD reset_interrupt //; reset Handler
DCD IntDefaultHandler // ; GPIO Port C
DCD IntDefaultHandler //; GPIO Port D
DCD IntDefaultHandler //; GPIO Port E
DCD uart0_interrupt //; UART0
DCD IntDefaultHandler //; UART1
DCD IntDefaultHandler // ; SSI
DCD IntDefaultHandler //; I2C
DCD IntDefaultHandler //; PWM Fault
DCD IntDefaultHandler //; PWM Generator 0
DCD IntDefaultHandler //; PWM Generator 1
DCD IntDefaultHandler //; PWM Generator 2
DCD IntDefaultHandler //; Quadrature Encoder
DCD IntDefaultHandler //; ADC Sequence 0
DCD IntDefaultHandler //; ADC Sequence 1
DCD IntDefaultHandler //; ADC Sequence 2
DCD IntDefaultHandler //; ADC Sequence 3
DCD IntDefaultHandler //; Watchdog
DCD timer0_interrupt //; Timer 0A
DCD IntDefaultHandler // ; Timer 0B
DCD IntDefaultHandler //; Timer 1A
DCD IntDefaultHandler //; Timer 1B
DCD IntDefaultHandler //; Timer 2A
DCD IntDefaultHandler //; Timer 2B
DCD IntDefaultHandler //; Comp 0
DCD IntDefaultHandler //; Comp 1
DCD IntDefaultHandler //; Comp 2
DCD IntDefaultHandler //; System Control
DCD IntDefaultHandler //; Flash Control
DCD IntDefaultHandler //; GPIO Port F
DCD IntDefaultHandler //; GPIO Port G
DCD IntDefaultHandler //; GPIO Port H
DCD IntDefaultHandler // ; UART2 Rx and Tx
DCD IntDefaultHandler // ; SSI1 Rx and Tx
DCD IntDefaultHandler // ; Timer 3 subtimer A
DCD IntDefaultHandler //; Timer 3 subtimer B
DCD IntDefaultHandler //; I2C1 Master and Slave
DCD IntDefaultHandler //; Quadrature Encoder 1
DCD IntDefaultHandler // ; CAN0
DCD IntDefaultHandler // ; CAN1
DCD IntDefaultHandler // ; CAN2
DCD eth_interrupt //; Ethernet
DCD IntDefaultHandler //; Hibernate
DCD IntDefaultHandler //; USB0
DCD IntDefaultHandler //; PWM Generator 3
DCD IntDefaultHandler // ; uDMA Software Transfer
DCD IntDefaultHandler // ; uDMA Error
c)调用Reset Handler
IMPORT _main //通知编译器要使用的标号在其他文件
B _main //把程序流程转到主应用程序
ALIGN //默认是字对齐方式,也说明了代码是4字节对齐的
|.text| 用于表示由 C 编译程序产生的代码段,或用于以某种方式与 C 库关联的代码段。
AREA |.text|, CODE, READONLY //定义C编译器源代码的代码段,只读
堆栈的初始化:
IF :DEF: __MICROLIB //“DEF”的用法——:DEF:X 就是说X定义了则为真,否则为假;如果定义了MICORLIB。
EXPORT __initial_sp //则将栈顶地址、
EXPORT __heap_base //堆起始地址、
EXPORT __heap_limit //堆末端界限地址赋予全局属性,使外部程序可调用
ELSE //如果没定义__MICROLIB,则使用默认的C运行时库
IMPORT __use_two_region_memory //通知编译器要使用的标号在其他文件
EXPORT __user_initial_stackheap
__user_initial_stackheap
//此处是初始化两区的堆栈空间,堆是从由低到高的增长,栈是由高向低生长的,两个是互相独立的数据段,并不能交叉使用。
LDR R0, =HeapMem //保存堆始地址
LDR R1, =(StackMem + Stack) //保存栈的大小
LDR R2, =(HeapMem + Heap) //保存堆的大小
LDR R3, =StackMem //保存栈顶指针
BX LR
ENDIF
;******************************************************************************
;
; Make sure the end of this section is aligned.
;
;******************************************************************************
ALIGN //填充字节使地址对齐
;******************************************************************************
;
; Tell the assembler that we're done.
;
;******************************************************************************
END //END 命令指示汇编器,已到达一个源文件的末尾。