NXP

ARM Cortex-M3的startup.s文件详解

2019-07-12 12:02发布

ARM Cortex-M3的startup.s文件详解原文地址链接LM3S9B90为例。Startup.s文件是系统的启动文件,主要包括堆和栈的初始化配置、中断向量表的配置以及将程序引导到main( )函数等。Startup.s主要完成三个工作:栈和堆的初始化、定位中断向量表、调用Reset Handlera)堆和栈的初始化Startup.s中的代码如下图所示:  1.程序分别对堆和栈进行了大小的规定以及空间的分配。
Stack   EQU     0x00002000     //定义栈的大小。EQU相当于汇编当中的宏定义,Stack替换0x00002000,即8*1024字节=8KBHeap    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.;以下为向量表,在复位时被映射到FLASH0地址。;******************************************************************************    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;栈顶指针,被放在向量表的开始,FLASH0地址,复位后首先装载栈顶指针        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 命令指示汇编器,已到达一个源文件的末尾。