一:启动代码简介
启动代码是芯片复位后进入C语言的main()函数前执行的一段代码。主要是为运行C语言程序提供基本的运行环境,初始化存储系统等。为了能够进行系统初始化,采用一个汇编文件作为启动代码是常见的做法。
二:启动代码的作用
1.初始化异常向量表
2.初始化存储器系统
3.初始化堆栈
程序使用编译器分配的空间作为堆栈,而不是按通常的做法爸堆栈分配到RAM的顶端。这样做的好处一是不必知道RAM顶端的位置,移植更加方便,二是编译器给出的占用RAM空间的大小就是实际占用的大小,便于控制RAM的分配。
4.初始化有特殊要求的端口、设备
5.初始化应用程序的运行环境
6.改变处理器的运行模式
7.调用主应用程序
三:startup_LPC11xx.s启动代码分析
;Stack Configuration
Stack_Size EQU 0x00000200 ; 定义statck_size标号为ox200的空间作为栈空间
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size ; 为栈分配内存空间,并初始化为0
__initial_sp
;Heap Configuration
Heap_Size EQU 0x00000200 ; 堆大小定义为0x00000000字节
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,???
; 为所有Handler分配内存单元
AREA RESET, DATA, READONLY ; 声明数据段RESET,放到数据段中为于0地址
; 该数据段内存单元只读
EXPORT __Vectors ; 声明一个全局的标号,该标号可在其他的文件中引用
__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 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
DCD SysTick_Handler ; SysTick Handler
; 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
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 :DEF:EN_CRP ; 宏判断是否定义NO_CRP
AREA |.ARM.__at_0x02FC|, CODE, READONLY ; 自定义只读代码段
CRP_Key DCD 0x87654321 ; 加密等级
ENDIF
AREA |.text|, CODE, READONLY ; 声明代码段|.text|,只读
; Reset Handler ; 复位入口子函数
Reset_Handler PROC ; PROC:子程序开始伪指令
EXPORT Reset_Handler [WEAK] ; __main()是编译系统提供的一个函数
IMPORT __main ; 负责完成库函数的初始化和初始化应用程序执行环境
LDR R0, =__main ; 使用=标示目前为伪指令,=等于@取地址,把__main的地址给R0
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 ; 检查是否定义了__MICROLIB,在编译器中设置
; 有时候使用外部microlib出错,注意是不是这个地方出错
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory ; 使用双段模式
EXPORT __user_initial_stackheap
__user_initial_stackheap ; 重新定义堆栈
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