文章目录
- 1.堆栈初始化(1)
- 2.预留字节,设置指令集架构THUMB
- 3.RESET区域存储中断向量表
- 3.1 Reset_Handler中断函数
- 3.2 NMI_Handler等中断函数
- 4.堆栈初始化(2)是否使用MICROLIB库
1.堆栈初始化(1)
;堆栈配置大小为0x400
Stack_Size EQU 0x00000400
;AREA用于声明一个内存区域的开始
;STACK定义内存区域的名称,表示程序的调用堆栈
;NOINIT表示内存区域不会被初始化(有些区域程序启动时可能被清零)
;READWRITE指定了内存区域的访问权限,既可以读也可以写
;ALIGN=3,制定了内存区域的对齐方式,2的3次幂=8字节对齐AREA STACK, NOINIT, READWRITE, ALIGN=3
;Stack_Mem是一个标签用于标识一个内存位置,用作堆栈起始地址的标签
;SPACE是一个汇编指令,用于在内存中预留一定数量的字节,不初始化这些字节
Stack_Mem SPACE Stack_Size
;__initial_sp表示初始化堆栈指针的地址
__initial_sp; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>Heap_Size EQU 0x00000200AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
;__heap_limit是一个标签,表示内存区域的结束地址
__heap_limit
2.预留字节,设置指令集架构THUMB
;PRESERVE8用于指示编译器保留接下来的8个字节,以确保特定的对齐或填充需求。
;THUMB 是一种用于ARM架构的指令集,它允许使用16位的指令而不是标准的32位PRESERVE8THUMB
3.RESET区域存储中断向量表
实际上就是留好函数的地址,可以指向c语言中重构的相同名称的函数,当触发中断时,直接调用。并且在中断向量表中用DCD指令,定义好名称,留好位置。
; Vector Table Mapped to Address 0 at Reset
;用AREA指令定义RESET区域,用于存储数据(这里指中断向量表),只读
;EXPORT指__Vectors、__Vectors_End、__Vectors_Size,这三个标签是对外可用的AREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size;中断向量表,DCD指令(Define Constant Doubleword)定义一个双字常量(32位)
__Vectors DCD __initial_sp ; Top of StackDCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault HandlerDCD BusFault_Handler ; Bus Fault HandlerDCD UsageFault_Handler ; Usage Fault HandlerDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD SVC_Handler ; SVCall HandlerDCD DebugMon_Handler ; Debug Monitor HandlerDCD 0 ; ReservedDCD PendSV_Handler ; PendSV HandlerDCD SysTick_Handler ; SysTick Handler;External InterruptsDCD DMA0_Channel0_IRQHandler ;DMA channel 0 transfer completeDCD DMA0_Channel1_IRQHandler ;DMA channel 1 transfer completeDCD DMA0_Channel2_IRQHandler ;DMA channel 2 transfer completeDCD DMA0_Channel3_IRQHandler ;DMA channel 3 transfer completeDCD DMA0_Channel4_IRQHandler ;DMA channel 4 transfer completeDCD DMA0_Channel5_IRQHandler ;DMA channel 5 transfer completeDCD DMA0_Channel6_IRQHandler ;DMA channel 6 transfer completeDCD DMA0_Channel7_IRQHandler ;DMA channel 7 transfer completeDCD DMA0_Channel8_IRQHandler ;DMA channel 8 transfer completeDCD DMA0_Channel9_IRQHandler ;DMA channel 9 transfer completeDCD DMA0_Channel10_IRQHandler ;DMA channel 10 transfer completeDCD DMA0_Channel11_IRQHandler ;DMA channel 11 transfer completeDCD DMA0_Channel12_IRQHandler ;DMA channel 12 transfer completeDCD DMA0_Channel13_IRQHandler ;DMA channel 13 transfer completeDCD DMA0_Channel14_IRQHandler ;DMA channel 14 transfer completeDCD DMA0_Channel15_IRQHandler ;DMA channel 15 transfer completeDCD PORTA_IRQHandler ;Port A pin detect interruptDCD PORTB_IRQHandler ;Port B pin detect interruptDCD PORTC_IRQHandler ;Port C pin detect interruptDCD PORTD_IRQHandler ;Port D pin detect interruptDCD PORTE_IRQHandler ;Port E pin detect interruptDCD UART0_IRQHandler ;UART0 Transmit / Receive InterruptDCD UART1_IRQHandler ;UART1 Transmit / Receive InterruptDCD UART2_IRQHandler ;UART2 Transmit / Receive InterruptDCD UART3_IRQHandler ;UART3 Transmit / Receive InterruptDCD 0 ;ReservedDCD 0 ;ReservedDCD SPI0_IRQHandler ;SPI0 InterruptDCD SPI1_IRQHandler ;SPI1 InterruptDCD SPI2_IRQHandler ;SPI2 InterruptDCD 0 ;ReservedDCD I2C0_IRQHandler ;I2C0 InterruptDCD 0 ;ReservedDCD EIO_IRQHandler ;EIO InterruptDCD CAN0_IRQHandler ;CAN0 InterruptDCD CAN0_Wakeup_IRQHandler ;CAN0 Wakeup InterruptDCD CAN1_IRQHandler ;CAN1 InterruptDCD CAN1_Wakeup_IRQHandler ;CAN1 Wakeup InterruptDCD CAN2_IRQHandler ;CAN2 InterruptDCD CAN2_Wakeup_IRQHandler ;CAN2 Wakeup InterruptDCD CAN3_IRQHandler ;CAN3 InterruptDCD CAN3_Wakeup_IRQHandler ;CAN3 Wakeup InterruptDCD 0 ;ReservedDCD 0 ;ReservedDCD 0 ;ReservedDCD 0 ;ReservedDCD PDT0_IRQHandler ;PDT0 InterruptDCD PDT1_IRQHandler ;PDT1 InterruptDCD ADC0_IRQHandler ;ADC0 InterruptDCD ADC1_IRQHandler ;ADC1 InterruptDCD ACMP0_IRQHandler ;ACMP0 InterruptDCD WDG_IRQHandler ;WDG InterruptDCD EWDG_IRQHandler ;EWDG InterruptDCD MCM_IRQHandler ;MCM InterruptDCD LVD_IRQHandler ;LVD InterruptDCD SPM_IRQHandler ;SPM InterruptDCD RCM_IRQHandler ;RCM InterruptDCD PWM0_Overflow_IRQHandler ;PWM0 Overflow InterruptDCD PWM0_Channel_IRQHandler ;PWM0 Channel InterruptDCD PWM0_Fault_IRQHandler ;PWM0 Fault InterruptDCD PWM1_Overflow_IRQHandler ;PWM1 Overflow InterruptDCD PWM1_Channel_IRQHandler ;PWM1 Channel InterruptDCD PWM1_Fault_IRQHandler ;PWM1 Fault InterruptDCD PWM2_Overflow_IRQHandler ;PWM2 Overflow InterruptDCD PWM2_Channel_IRQHandler ;PWM2 Channel InterruptDCD PWM2_Fault_IRQHandler ;PWM2 Fault InterruptDCD PWM3_Overflow_IRQHandler ;PWM3 Overflow InterruptDCD PWM3_Channel_IRQHandler ;PWM3 Channel InterruptDCD PWM3_Fault_IRQHandler ;PWM3 Fault InterruptDCD PWM4_Overflow_IRQHandler ;PWM4 Overflow InterruptDCD PWM4_Channel_IRQHandler ;PWM4 Channel InterruptDCD PWM4_Fault_IRQHandler ;PWM4 Fault InterruptDCD PWM5_Overflow_IRQHandler ;PWM5 Overflow InterruptDCD PWM5_Channel_IRQHandler ;PWM5 Channel InterruptDCD PWM5_Fault_IRQHandler ;PWM5 Fault InterruptDCD 0 ;ReservedDCD 0 ;ReservedDCD 0 ;ReservedDCD 0 ;ReservedDCD 0 ;ReservedDCD 0 ;ReservedDCD RTC_IRQHandler ;RTC InterruptDCD PCT_IRQHandler ;PCT InterruptDCD TIMER_Channel0_IRQHandler ;TIMER Channel0 InterruptDCD TIMER_Channel1_IRQHandler ;TIMER Channel1 InterruptDCD TIMER_Channel2_IRQHandler ;TIMER Channel2 InterruptDCD TIMER_Channel3_IRQHandler ;TIMER Channel3 InterruptDCD CSE_IRQHandler ;CSE InterruptDCD FLASH_ECC_IRQHandler ;Flash ECC InterruptDCD FLASH_IRQHandler ;Flash InterruptDCD FLASH_Collision_IRQHandler ;Flash Collision InterruptDCD ECC_1BIT_IRQHandler ;ECC 1BIT InterruptDCD ECC_2BIT_IRQHandler ;ECC 2BIT Interrupt__Vectors_End;两个标签相减,求出大小使用竖线 | 包围 .text 是一种语法,
;通常用于表示这个名称是一个保留字或者是一个有特殊意义的标识符。
;在某些汇编器中,.text 可能是一个保留用于代码存储的区域的默认名称,
;因此使用竖线来确保名称的唯一性和避免与普通标签或常量名称冲突。__Vectors_Size EQU __Vectors_End - __VectorsAREA |.text|, CODE, READONLY
3.1 Reset_Handler中断函数
; Reset handler
;PROC表示一个新的过程或代码块的开始
;CPSID 指令设置优先级掩码,I 参数表示禁用中断。这通常在处理程序开始时执行,以防止在初始化完成之前发生中断。
Reset_Handler PROCEXPORT Reset_Handler [WEAK]CPSID I ; Mask interrupts;检查是否定义了 NOT_INIT_SRAM_AFTER_RESET变量,如果定义了,才执行下面的程序IF :DEF:NOT_INIT_SRAM_AFTER_RESET; Check reset status, if there is any reset except power on and lvr, don't init SRAMLDR R0, =0x4000001CLDR R1, [R0]AND R1, R1, #0x30000CMP R1, #0x00000
;如果相等,则表示LDR和POR是无效状态,需要跳转到ECC_INIT_END0BEQ ECC_INIT_END0ENDIF;无条件跳转到 ECC_INIT_END0B ECC_INIT_END0; Init ECC SRAMLDR R1, =0x1FFF0000LDR R2, =0x2000F000
;R2=R2-R1SUBS R2, R1SUBS R2, #1
;如果上面的结果R2是非正数(<=0),则跳转到ECC_INIT_END0BLE ECC_INIT_END0
;将立即数0移动到R0寄存器MOVS R0, #0MOVS R3, #4
;标签,表示循环的开始
LOOP0STR R0, [R1]ADD R1, R1, R3SUBS R2, #4
;如果 R2 寄存器的值是非负数(即大于或等于零),则跳转到 LOOP0 继续循环。BGE LOOP0
ECC_INIT_END0IMPORT SystemInitIMPORT __mainLDR R0, =SystemInit
;调用R0指向的函数(SystemInit)BLX R0IF :DEF:NOT_INIT_SRAM_AFTER_RESET; Clear reset statusLDR R0, =0x4000001CLDR R1, =0x80000000;STR 指令(Store Register)在汇编语言中用于将数据从寄存器存储到内存STR R1, [R0]ENDIFCPSIE I ; Unmask interruptsLDR R0, =__mainBX R0ENDP
3.2 NMI_Handler等中断函数
; Dummy Exception Handlers (infinite loops which can be modified)NMI_Handler PROCEXPORT NMI_Handler [WEAK];B .表示死循环,这里主要是提供一个接口,留一个4字节的程序地址;用WEAK,等待在c语言里调用B .ENDP
HardFault_Handler\PROCEXPORT HardFault_Handler [WEAK]B .ENDP
MemManage_Handler\PROCEXPORT MemManage_Handler [WEAK]B .ENDP
BusFault_Handler\PROCEXPORT BusFault_Handler [WEAK]B .ENDP
UsageFault_Handler\PROCEXPORT UsageFault_Handler [WEAK]B .ENDP
SVC_Handler PROCEXPORT SVC_Handler [WEAK]B .ENDP
DebugMon_Handler\PROCEXPORT DebugMon_Handler [WEAK]B .ENDP
PendSV_Handler PROCEXPORT PendSV_Handler [WEAK]B .ENDP
SysTick_Handler PROCEXPORT SysTick_Handler [WEAK]B .ENDP;
Default_Handler PROCEXPORT DMA0_Channel0_IRQHandler [WEAK]EXPORT DMA0_Channel1_IRQHandler [WEAK]EXPORT DMA0_Channel2_IRQHandler [WEAK]EXPORT DMA0_Channel3_IRQHandler [WEAK]EXPORT DMA0_Channel4_IRQHandler [WEAK]EXPORT DMA0_Channel5_IRQHandler [WEAK]EXPORT DMA0_Channel6_IRQHandler [WEAK]EXPORT DMA0_Channel7_IRQHandler [WEAK]EXPORT DMA0_Channel8_IRQHandler [WEAK]EXPORT DMA0_Channel9_IRQHandler [WEAK]EXPORT DMA0_Channel10_IRQHandler [WEAK]EXPORT DMA0_Channel11_IRQHandler [WEAK]EXPORT DMA0_Channel12_IRQHandler [WEAK]EXPORT DMA0_Channel13_IRQHandler [WEAK]EXPORT DMA0_Channel14_IRQHandler [WEAK]EXPORT DMA0_Channel15_IRQHandler [WEAK]EXPORT PORTA_IRQHandler [WEAK]EXPORT PORTB_IRQHandler [WEAK]EXPORT PORTC_IRQHandler [WEAK]EXPORT PORTD_IRQHandler [WEAK]EXPORT PORTE_IRQHandler [WEAK]EXPORT UART0_IRQHandler [WEAK]EXPORT UART1_IRQHandler [WEAK]EXPORT UART2_IRQHandler [WEAK]EXPORT UART3_IRQHandler [WEAK]EXPORT SPI0_IRQHandler [WEAK]EXPORT SPI1_IRQHandler [WEAK]EXPORT SPI2_IRQHandler [WEAK]EXPORT I2C0_IRQHandler [WEAK]EXPORT EIO_IRQHandler [WEAK]EXPORT CAN0_IRQHandler [WEAK]EXPORT CAN0_Wakeup_IRQHandler [WEAK]EXPORT CAN1_IRQHandler [WEAK]EXPORT CAN1_Wakeup_IRQHandler [WEAK]EXPORT CAN2_IRQHandler [WEAK]EXPORT CAN2_Wakeup_IRQHandler [WEAK]EXPORT CAN3_IRQHandler [WEAK]EXPORT CAN3_Wakeup_IRQHandler [WEAK]EXPORT PDT0_IRQHandler [WEAK]EXPORT PDT1_IRQHandler [WEAK]EXPORT ADC0_IRQHandler [WEAK]EXPORT ADC1_IRQHandler [WEAK]EXPORT ACMP0_IRQHandler [WEAK]EXPORT WDG_IRQHandler [WEAK]EXPORT EWDG_IRQHandler [WEAK]EXPORT MCM_IRQHandler [WEAK]EXPORT LVD_IRQHandler [WEAK]EXPORT SPM_IRQHandler [WEAK]EXPORT RCM_IRQHandler [WEAK]EXPORT PWM0_Overflow_IRQHandler [WEAK]EXPORT PWM0_Channel_IRQHandler [WEAK]EXPORT PWM0_Fault_IRQHandler [WEAK]EXPORT PWM1_Overflow_IRQHandler [WEAK]EXPORT PWM1_Channel_IRQHandler [WEAK]EXPORT PWM1_Fault_IRQHandler [WEAK]EXPORT PWM2_Overflow_IRQHandler [WEAK]EXPORT PWM2_Channel_IRQHandler [WEAK]EXPORT PWM2_Fault_IRQHandler [WEAK]EXPORT PWM3_Overflow_IRQHandler [WEAK]EXPORT PWM3_Channel_IRQHandler [WEAK]EXPORT PWM3_Fault_IRQHandler [WEAK]EXPORT PWM4_Overflow_IRQHandler [WEAK]EXPORT PWM4_Channel_IRQHandler [WEAK]EXPORT PWM4_Fault_IRQHandler [WEAK]EXPORT PWM5_Overflow_IRQHandler [WEAK]EXPORT PWM5_Channel_IRQHandler [WEAK]EXPORT PWM5_Fault_IRQHandler [WEAK]EXPORT RTC_IRQHandler [WEAK]EXPORT PCT_IRQHandler [WEAK]EXPORT TIMER_Channel0_IRQHandler [WEAK]EXPORT TIMER_Channel1_IRQHandler [WEAK]EXPORT TIMER_Channel2_IRQHandler [WEAK]EXPORT TIMER_Channel3_IRQHandler [WEAK]EXPORT CSE_IRQHandler [WEAK]EXPORT FLASH_ECC_IRQHandler [WEAK]EXPORT FLASH_IRQHandler [WEAK]EXPORT FLASH_Collision_IRQHandler [WEAK]EXPORT ECC_1BIT_IRQHandler [WEAK]EXPORT ECC_2BIT_IRQHandler [WEAK]
DMA0_Channel0_IRQHandler
DMA0_Channel1_IRQHandler
DMA0_Channel2_IRQHandler
DMA0_Channel3_IRQHandler
DMA0_Channel4_IRQHandler
DMA0_Channel5_IRQHandler
DMA0_Channel6_IRQHandler
DMA0_Channel7_IRQHandler
DMA0_Channel8_IRQHandler
DMA0_Channel9_IRQHandler
DMA0_Channel10_IRQHandler
DMA0_Channel11_IRQHandler
DMA0_Channel12_IRQHandler
DMA0_Channel13_IRQHandler
DMA0_Channel14_IRQHandler
DMA0_Channel15_IRQHandler
PORTA_IRQHandler
PORTB_IRQHandler
PORTC_IRQHandler
PORTD_IRQHandler
PORTE_IRQHandler
UART0_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
UART3_IRQHandler
SPI0_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
I2C0_IRQHandler
EIO_IRQHandler
CAN0_IRQHandler
CAN0_Wakeup_IRQHandler
CAN1_IRQHandler
CAN1_Wakeup_IRQHandler
CAN2_IRQHandler
CAN2_Wakeup_IRQHandler
CAN3_IRQHandler
CAN3_Wakeup_IRQHandler
PDT0_IRQHandler
PDT1_IRQHandler
ADC0_IRQHandler
ADC1_IRQHandler
ACMP0_IRQHandler
WDG_IRQHandler
EWDG_IRQHandler
MCM_IRQHandler
LVD_IRQHandler
SPM_IRQHandler
RCM_IRQHandler
PWM0_Overflow_IRQHandler
PWM0_Channel_IRQHandler
PWM0_Fault_IRQHandler
PWM1_Overflow_IRQHandler
PWM1_Channel_IRQHandler
PWM1_Fault_IRQHandler
PWM2_Overflow_IRQHandler
PWM2_Channel_IRQHandler
PWM2_Fault_IRQHandler
PWM3_Overflow_IRQHandler
PWM3_Channel_IRQHandler
PWM3_Fault_IRQHandler
PWM4_Overflow_IRQHandler
PWM4_Channel_IRQHandler
PWM4_Fault_IRQHandler
PWM5_Overflow_IRQHandler
PWM5_Channel_IRQHandler
PWM5_Fault_IRQHandler
RTC_IRQHandler
PCT_IRQHandler
TIMER_Channel0_IRQHandler
TIMER_Channel1_IRQHandler
TIMER_Channel2_IRQHandler
TIMER_Channel3_IRQHandler
CSE_IRQHandler
FLASH_ECC_IRQHandler
FLASH_IRQHandler
FLASH_Collision_IRQHandler
ECC_1BIT_IRQHandler
ECC_2BIT_IRQHandlerB .ENDPALIGN
4.堆栈初始化(2)是否使用MICROLIB库
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
;文件末尾部分处理了两种内存分配方式:
;使用标准库(__MICROLIB 未定义)和不使用标准库的情况。
;在不使用标准库的情况下,定义了 __user_initial_stackheap 函数,用于初始化堆栈和堆。IF :DEF:__MICROLIBEXPORT __initial_spEXPORT __heap_baseEXPORT __heap_limitELSEIMPORT __use_two_region_memoryEXPORT __user_initial_stackheap__user_initial_stackheapLDR R0, = Heap_MemLDR R1, =(Stack_Mem + Stack_Size)LDR R2, = (Heap_Mem + Heap_Size)LDR R3, = Stack_Mem
;将控制权返回给调用者。在这里,它将返回到调用 BX 指令之前的地址,
;这里是堆栈起始地址Stack_MemBX LRALIGNENDIFEND;****************END OF FILE******************************************