飞思卡尔Kinetis L 汇编语言启动文件startup_MK25Z4简单分析
2017-07-23
打开Freedom KL25的例程包,任意找一个code example,以lower_power_dma_uart_demo为例,分析一下启动汇编文件的代码。
代码主要分三部分:堆栈等的配置、向量表、初始启动跳转。
1. 堆栈配置
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x00000800
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp EQU 0x20002ff8
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
注:AREA关键字的作用是告诉汇编器,该section是独立的一段,应该重新开始解析。AREA后面的一系列表示该段的属性。
SPACE关键字告诉其后的一段memory存储空间,不被初始化为某些特定值,与FILL相对。
EQU可以理解为等于。
2. 向量表
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD DMA0_IRQHandler ; DMA channel 0 transfer complete interrupt
DCD DMA1_IRQHandler ; DMA channel 1 transfer complete interrupt
DCD DMA2_IRQHandler ; DMA channel 2 transfer complete interrupt
DCD DMA3_IRQHandler ; DMA channel 3 transfer complete interrupt
DCD Reserved20_IRQHandler ; Reserved interrupt 20
DCD FTFA_IRQHandler ; FTFA interrupt
DCD LVD_LVW_IRQHandler ; Low Voltage Detect, Low Voltage Warning
DCD LLW_IRQHandler ; Low Leakage Wakeup
DCD I2C0_IRQHandler ; I2C0 interrupt
DCD I2C1_IRQHandler ; I2C0 interrupt 25
DCD SPI0_IRQHandler ; SPI0 interrupt
DCD SPI1_IRQHandler ; SPI1 interrupt
DCD UART0_IRQHandler ; UART0 status/error interrupt
DCD UART1_IRQHandler ; UART1 status/error interrupt
DCD UART2_IRQHandler ; UART2 status/error interrupt
DCD ADC0_IRQHandler ; ADC0 interrupt
DCD CMP0_IRQHandler ; CMP0 interrupt
DCD TPM0_IRQHandler ; TPM0 fault, overflow and channels interrupt
DCD TPM1_IRQHandler ; TPM1 fault, overflow and channels interrupt
DCD TPM2_IRQHandler ; TPM2 fault, overflow and channels interrupt
DCD RTC_IRQHandler ; RTC interrupt
DCD RTC_Seconds_IRQHandler ; RTC seconds interrupt
DCD PIT_IRQHandler ; PIT timer interrupt
DCD Reserved39_IRQHandler ; Reserved interrupt 39
DCD USB0_IRQHandler ; USB0 interrupt
DCD DAC0_IRQHandler ; DAC interrupt
DCD TSI0_IRQHandler ; TSI0 interrupt
DCD MCG_IRQHandler ; MCG interrupt
DCD LPTimer_IRQHandler ; LPTimer interrupt
DCD Reserved45_IRQHandler ; Reserved interrupt 45
DCD PORTA_IRQHandler ; Port A interrupt
DCD PORTD_IRQHandler ; Port D interrupt
向量表很长,此处只截取一部分,这些向量表中的向量的默认名字就在这里指定了。开发人员只需将中断向量函数的具体功能实现即可。当然,有一些默认的dummy 异常handler已经有了,都是死循环:
; 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
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
3. 启动代码
启动代码就放在Reset复位向量里面,因为Reset向量是MCU启动时候第一个进入到PC寄存器并开始执行的地方。
; Reset Handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
启动代码首先将SystemInit的地址load到R0寄存器中,然后使用BLX跳转指令跳到SystemInit函数开始处去执行,执行完毕以后再执行main函数的执行。
接下去需要找SystemInit的代码查看。