从大学时期,使用的第一块ARM单片机——飞思卡尔K60起,到后面参加工作 STM32,I.MX RT系列,Infineon 的 TLE984等等。从当初啥外设都不知,只会在main函数里写个 printf,到现在对ARM架构略知一二。接下来笔者来重点说明下,我们常常见到的startup.s文件。也就是常说的启动文件
若连一个单片机是怎么启动都不知道,只知道在while(1)里写代码,这就常说的只会敲代码的码农,还不算一个完整的嵌入式工程师吧。这里笔者就拿最近在用的 i.MX RT1052来讲,cortex M7 一款性价比贼高的跨界处理器。下面的描述都是笔者通过相关书籍或网络整理后的笔记内容:
PRESERVE8 ; 8 字节对齐
THUMB ; THUMB指令集
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY ; 声明权限为"READONLY" 名称为"RESET"的数据段
EXPORT __Vectors ; 导出"__Vectors"标号,理解为向量表收地址,分散加载描述文件中会用到
EXPORT __Vectors_End
EXPORT __Vectors_Size
IMPORT |Image$$ARM_LIB_STACK$$ZI$$Limit| ; 导入"|Image$$ARM_LIB_STACK$$ZI$$Limit|"
__Vectors DCD |Image$$ARM_LIB_STACK$$ZI$$Limit| ; 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 ;操作系统会用到的异常向量
DCD SysTick_Handler ;操作系统会用到的滴答定时器异常向量(没有操作系统时可以用作普通定时器中断,这里强烈建议这么用)
DCD DMA0_DMA16_IRQHandler ;DMA channel 0/16 transfer complete
DCD DMA1_DMA17_IRQHandler ;DMA channel 1/17 transfer complete
DCD DMA2_DMA18_IRQHandler ;DMA channel 2/18 transfer complete
DCD DMA3_DMA19_IRQHandler ;DMA channel 3/19 transfer complete
DCD DMA4_DMA20_IRQHandler ;DMA channel 4/20 transfer complete
DCD DMA5_DMA21_IRQHandler ;DMA channel 5/21 transfer complete
......
DCD DefaultISR ;251
DCD DefaultISR ;252
DCD DefaultISR ;253
DCD DefaultISR ;254
DCD 0xFFFFFFFF ; Reserved for user TRIM value
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA RES_HANDLER, CODE, READONLY
; Reset Handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
CPSID I ; Mask interrupts
LDR R0, =0xE000ED08 ;
LDR R1, =__Vectors
STR R1, [R0]
LDR R2, [R1]
MSR MSP, R2
;Config OCRAM,DTCM,ITCM
LDR R0,=0x400AC038
LDR R1,=0x00AA0000
STR R1,[R0]
LDR R0,=0x400AC040
LDR R1,=0x00200007
STR R1,[R0]
LDR R0,=0x400AC044
LDR R1,=0xFFFFAAA9 ;OCRAM = 32KB, DTCM = 224KB ,ITCM = 256KB 这里定义RAM分配,不是每个MCU都是这样的
STR R1,[R0]
LDR R0, =SystemInit
BLX R0
CPSIE i ; Unmask interrupts
LDR R0, =__main ;__main 不是我们所理解的 main函数
BX R0
ENDP
AREA OTHER_HANDLER, CODE, READONLY
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler\
PROC
EXPORT NMI_Handler [WEAK]
B . ;这里实现死循环 类似 while(1)
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
......
ENET_1588_Timer_IRQHandler\
PROC
EXPORT ENET_1588_Timer_IRQHandler [WEAK]
LDR R0, =ENET_1588_Timer_DriverIRQHandler
BX R0
ENDP
Default_Handler\
PROC
EXPORT DMA0_DMA16_DriverIRQHandler [WEAK]
EXPORT DMA1_DMA17_DriverIRQHandler [WEAK]
EXPORT DMA2_DMA18_DriverIRQHandler [WEAK]
......
PWM4_1_IRQHandler
PWM4_2_IRQHandler
PWM4_3_IRQHandler
PWM4_FAULT_IRQHandler
Reserved168_IRQHandler
Reserved169_IRQHandler
Reserved170_IRQHandler
Reserved171_IRQHandler
Reserved172_IRQHandler
Reserved173_IRQHandler
SJC_ARM_DEBUG_IRQHandler
NMI_WAKEUP_IRQHandler
DefaultISR
LDR R0, =DefaultISR
BX R0
ENDP
ALIGN
END