单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4398|回复: 0
收起左侧

分析 startup_LPC11xx.s 启动代码

[复制链接]
liuyuxi 发表于 2015-1-10 20:30 | 显示全部楼层 |阅读模式
  在ARM中,无法直接执行 main 函数,需要额外的启动代码来为运行C语言程序设置基本的
运行环境,初始化存储系统等。为了进行下系统初始化,采用汇编文件作为启动代码。

启动代码的作用
1.初始化异常向量表
    当M0产生异常(中断)时,需要跳转到相应的函数中执行。如串口中断等。。。
    需要在启动文件中构建异常向量表。

2.初始化存储器系统
3.初始化堆栈
    程序使用编译器分配的空间作为堆栈,而不是按通常的做法爸堆栈分配到RAM的顶端。这样做的好处一是不必知道RAM顶端的位置,移植更加方便,二是编译器给出的占用RAM空间的大小就是实际占用的大小,便于控制RAM的分配。
4.初始化有特殊要求的端口、设备
5.初始化应用程序的运行环境
6.改变处理器的运行模式
7.调用主应用程序

    当所有执行完毕后,才会调用我们写的main()函数


参考资料:http://www.51hei.com/bbs/dpj-30365-1.html

startup_LPC11xx.s :

;/*****************************************************************************
; * @file:    startup_LPC11xx.s
; * @purpose: CMSIS Cortex-M0 Core Device Startup File
; *           for the NXP LPC11xx Device Series
; * @version: V1.0
; * @date:    25. Nov. 2008
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
; *
; * Copyright (C) 2008 ARM Limited. All rights reserved.
; * ARM Limited (ARM) is supplying this software for use with Cortex-M0
; * processor based microcontrollers.  This file can be freely distributed
; * within development tools that are supporting such ARM based processors.
; *
; * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
; *
; *****************************************************************************/


; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x00000100                          ; 定义Stack_Size 标号为0x100的空间作为栈空间

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size                          ; 为栈分配内存空间,并初始化为0
__initial_sp


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

Heap_Size       EQU     0x00000000                              ; 堆大小定义为 0

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size                            ; 为堆分配内存空间,并初始化为0
__heap_limit                                                                    ; 堆地址的标号

                PRESERVE8                                           ; 当前堆栈保持8字节对齐                                   
                THUMB                                                   ; 指示编译器为 thumb 指令


; 定义异常向量表

; Vector Table Mapped to Address 0 at Reset 向量表映射到复位地址 0

                AREA    RESET, DATA, READONLY             ; 声明数据段RESET,放到数据段中为于0地址,其实放在CODE区
                                                                                          ; 该数据段内存单元只读
                            EXPORT  __Vectors                           ; 声明一个全局的标号,该标号可在其他的文件中引用

/*
        DCD伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。DCD也可用“&”代替。
        */                               
__Vectors       DCD     __initial_sp              ; Top of Stack                    ; 给__initial_sp分配4字节32位的地址
                DCD     Reset_Handler             ; Reset Handler                    ;给标号Reset_Handler分配地址
                DCD     NMI_Handler               ; 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
                DCD     0                         ; Reserved
                DCD     SVC_Handler               ; SVCall Handler
                DCD     DebugMon_Handler          ; Debug Monitor Handler
                DCD     0                         ; Reserved
                ;DCD     PendSV_Handler           ; PendSV Handler
                                IMPORT  OS_CPU_PendSVHandler
                                DCD                OS_CPU_PendSVHandler
                ;DCD     SysTick_Handler           ; SysTick Handler
                                IMPORT        OS_CPU_SysTickHandler
                                DCD                OS_CPU_SysTickHandler           ; DCD伪指令用于分配一片连续的字存储单元并用指定的表达式初始化

                ; External Interrupts
                DCD     WAKEUP_IRQHandler         ; 15 wakeup sources for all the
                DCD     WAKEUP_IRQHandler         ; I/O pins starting from PIO0 (0:11)
                DCD     WAKEUP_IRQHandler         ; all 40 are routed to the same ISR                       
                DCD     WAKEUP_IRQHandler                        
                DCD     WAKEUP_IRQHandler                        
                DCD     WAKEUP_IRQHandler
                DCD     WAKEUP_IRQHandler
                DCD     WAKEUP_IRQHandler                       
                DCD     WAKEUP_IRQHandler                        
                DCD     WAKEUP_IRQHandler                        
                DCD     WAKEUP_IRQHandler
                DCD     WAKEUP_IRQHandler
                DCD     WAKEUP_IRQHandler         ; PIO1 (0:11)
                DCD     CAN_IRQHandler            ; CAN               
                DCD     SSP1_IRQHandler           ; SSP1               
                DCD     I2C_IRQHandler            ; I2C
                DCD     TIMER16_0_IRQHandler      ; 16-bit Timer0
                DCD     TIMER16_1_IRQHandler      ; 16-bit Timer1
                DCD     TIMER32_0_IRQHandler      ; 32-bit Timer0
                DCD     TIMER32_1_IRQHandler      ; 32-bit Timer1
                DCD     SSP0_IRQHandler           ; SSP0
                DCD     UART_IRQHandler           ; UART                ; 串口中断产生时 将跳转到 void UART_IRQHandler(void)
                DCD     USB_IRQHandler            ; USB IRQ
                DCD     USB_FIQHandler            ; USB FIQ
                DCD     ADC_IRQHandler            ; A/D Converter
                DCD     WDT_IRQHandler            ; Watchdog timer
                DCD     BOD_IRQHandler            ; Brown Out Detect
                DCD     FMC_IRQHandler            ; IP2111 Flash Memory Controller
                DCD     PIOINT3_IRQHandler        ; PIO INT3   
                DCD     PIOINT2_IRQHandler        ; PIO INT2
                DCD     PIOINT1_IRQHandler        ; PIO INT1
                DCD     PIOINT0_IRQHandler        ; PIO INT0  


                IF      :LNOT::DEF:NO_CRP                         ; 宏判断是否定义NO_CRP
                AREA    |.ARM.__at_0x02FC|, CODE, READONLY          ; 自定义只读代码段
CRP_Key         DCD     0xFFFFFFFF                                        ; 加密等级  
                ENDIF


                AREA    |.text|, CODE, READONLY                ; 声明代码段|.text|,只读


; Reset Handler                        ; 复位入口子函数 复位后执行的函数

Reset_Handler   PROC                                                                ; PROC:子程序开始伪指令
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main                                                ; __main()是编译系统提供的一个函数
                                                                                                    
                        LDR     R0, =__main                                    ; 负责完成库函数的初始化和初始化应用程序执行环境
                BX      R0                                                           ; 跳转到编译系统的__main(),最后自动跳转到用户程序的main()
                ENDP                                                                   ; 子程序结束
                                                                                                         

; Dummy Exception Handlers (infinite loops which can be modified)               

NMI_Handler     PROC
                EXPORT  NMI_Handler               [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler         [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler         [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler          [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler        [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler               [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler          [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler            [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler           [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WAKEUP_IRQHandler         [WEAK]
                EXPORT  CAN_IRQHandler            [WEAK]
                EXPORT  SSP1_IRQHandler           [WEAK]
                EXPORT  I2C_IRQHandler            [WEAK]
                EXPORT  TIMER16_0_IRQHandler      [WEAK]
                EXPORT  TIMER16_1_IRQHandler      [WEAK]
                EXPORT  TIMER32_0_IRQHandler      [WEAK]
                EXPORT  TIMER32_1_IRQHandler      [WEAK]
                EXPORT  SSP0_IRQHandler           [WEAK]
                EXPORT  UART_IRQHandler           [WEAK]

                EXPORT  USB_IRQHandler            [WEAK]
                EXPORT  USB_FIQHandler            [WEAK]
                EXPORT  ADC_IRQHandler            [WEAK]
                EXPORT  WDT_IRQHandler            [WEAK]
                EXPORT  BOD_IRQHandler            [WEAK]
                EXPORT  FMC_IRQHandler            [WEAK]
                EXPORT  PIOINT3_IRQHandler        [WEAK]
                EXPORT  PIOINT2_IRQHandler        [WEAK]
                EXPORT        PIOINT1_IRQHandler        [WEAK]
                EXPORT        PIOINT0_IRQHandler        [WEAK]


WAKEUP_IRQHandler
CAN_IRQHandler
SSP1_IRQHandler
I2C_IRQHandler
TIMER16_0_IRQHandler
TIMER16_1_IRQHandler
TIMER32_0_IRQHandler
TIMER32_1_IRQHandler
SSP0_IRQHandler
UART_IRQHandler
USB_IRQHandler
USB_FIQHandler
ADC_IRQHandler
WDT_IRQHandler
BOD_IRQHandler
FMC_IRQHandler
PIOINT3_IRQHandler  
PIOINT2_IRQHandler
PIOINT1_IRQHandler
PIOINT0_IRQHandler

                B       .

                ENDP


                ALIGN                                                        ; 添加补丁字节满足对齐


; User Initial Stack & Heap 用户初始化的堆栈

IF   :DEF:__MICROLIB   // “DEF”的用法:DEF:xx就是说xx定义了则为真,否则为假

        EXPORT __initial_sp   //则将栈顶定制
        EXPORT __heap_base   // 堆起始地址赋予全局属性
        EXPORT __heap_limit    //堆末端界限地址赋予全局属性,使外部程序可调用

        ELSE          //如果没有定义__MICROLIB,则使用默认的C运行时库

        IMPORT __use_two_region_memory   // 通知编译器要使用的标号在其他文件//__use_two_region_memory
         EXPORT __user_initial_stackheap   // 声明全局标号__user_initial_stackheap,这样外程序也可调用此标号
                          //则进行堆栈和堆的赋值,在__main函数执行过程中调用
                          //如果了使用默认的C库,程序启动过程中不会执行标号下//的代码




/**************************************************************************************************************************************************************

_user_initial_stackheap() 返回:

· r0 中的堆基址
        · r1 中的堆栈基址,即堆栈区中的最高地址
        · r2 中的堆限制
        · r3 中的堆栈限制,即堆栈区中的最低地址。

有单区模型和双区模型。

单区模型:(r0,r1)是单个堆栈和堆区。r1 大于 r0,并忽略 r2和r3。
        r0--r1这一块内存区域被堆和栈共用,堆从r0向上生长,栈从r1向下生长。

双区模型:(r0, r2)是初始堆,(r3, r1) 是初始堆栈。r2 大于或等于r0,r3小于r1。
        堆和栈分别指定了单独的内存区域。

**************************************************************************************************************************************************************/


__user_initial_stackheap   // 标号__user_initial_stackheap,表示拥护堆栈初始化程序入口
                       //则进行堆栈和堆得赋值,在__main函数执行过程中调用

        LDR   R0, = Heap_Mem  //保存堆起始地址
        LDR   R1, = (Stack_Mem + Stack_Size)  //保存栈的大小
        LDR   R2, = (Heap_Mem + Heap_Size)   // 保存堆得大小
        LDR   R3, = Stack_Mem // 保存栈顶指针
        BX   LR
         ALIGN    // 填充字节使地址对齐

                ENDIF

                END

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表