对startup_LPC17xx.s启动文件的认识

二话不说,首先贴上startup_LPC17xx.s文件的源码,如下所示:

;定义堆栈空间
Stack_Size      EQU     0x00001600			    			; 栈的大小为5632个字节
	 			AREA    STACK, NOINIT, READWRITE, ALIGN=3	; 定义一个段名为STACK的数据段,该段只保留内存单元,但是不进行初始化,可读可写,并且以8字节形式进行对齐
Stack_Mem       SPACE   Stack_Size							;为栈分配5632个字节的内存
__initial_sp												; 定义__initial_sp该标号为该栈的栈顶


Heap_Size       EQU     0x00000000
				AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base													; 定义	__heap_base该标号为该堆的起始地址
Heap_Mem        SPACE   Heap_Size
__heap_limit												; 定义	__heap_limit该标号为该堆的终止地址


            	PRESERVE8									; 指定当前文件 保持堆栈  8字节对齐的形式
            	THUMB										; 切换为THUMB指令集状态

                AREA    RESET, DATA, READONLY				; 定义一个段名为RESET的数据段,只可读





;创建中断向量表
            	EXPORT  __Vectors							; 声明函数 __Vectors (该函数在本文件中定义的,这样其余文件就可以调用本函数了)
			
__Vectors       DCD     __initial_sp              			; Top of Stack
				; DCD申请一个字(32bit)的内存空间,并赋一个初值,在这里,初值为一个函数的函数名,即函数的首地址
            	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

           		 ; External Interrupts,外部中断
            	DCD     WDT_IRQHandler            			; 16: Watchdog Timer
            	DCD     TIMER0_IRQHandler         			; 17: Timer0
            	DCD     TIMER1_IRQHandler         			; 18: Timer1
            	DCD     TIMER2_IRQHandler         			; 19: Timer2
            	DCD     TIMER3_IRQHandler         			; 20: Timer3
            	DCD     UART0_IRQHandler          			; 21: UART0
            	DCD     UART1_IRQHandler          			; 22: UART1
            	DCD     UART2_IRQHandler          			; 23: UART2
            	DCD     UART3_IRQHandler          			; 24: UART3
            	DCD     PWM1_IRQHandler          	 		; 25: PWM1
            	DCD     I2C0_IRQHandler           			; 26: I2C0
            	DCD     I2C1_IRQHandler           			; 27: I2C1
            	DCD     I2C2_IRQHandler          	 		; 28: I2C2
            	DCD     SPI_IRQHandler            			; 29: SPI
            	DCD     SSP0_IRQHandler           			; 30: SSP0
            	DCD     SSP1_IRQHandler          	 		; 31: SSP1
            	DCD     PLL0_IRQHandler           			; 32: PLL0 Lock (Main PLL)
            	DCD     RTC_IRQHandler            			; 33: Real Time Clock
            	DCD     EINT0_IRQHandler          			; 34: External Interrupt 0
            	DCD     EINT1_IRQHandler          			; 35: External Interrupt 1
            	DCD     EINT2_IRQHandler          			; 36: External Interrupt 2
            	DCD     EINT3_IRQHandler          			; 37: External Interrupt 3
            	DCD     ADC_IRQHandler            			; 38: A/D Converter
            	DCD     BOD_IRQHandler            			; 39: Brown-Out Detect
            	DCD     USB_IRQHandler            			; 40: USB
            	DCD     CAN_IRQHandler            			; 41: CAN
            	DCD     DMA_IRQHandler            			; 42: General Purpose DMA
            	DCD     I2S_IRQHandler            			; 43: I2S
            	DCD     ENET_IRQHandler           			; 44: Ethernet
            	DCD     RIT_IRQHandler            			; 45: Repetitive Interrupt Timer
            	DCD     MCPWM_IRQHandler          			; 46: Motor Control PWM
            	DCD     QEI_IRQHandler            			; 47: Quadrature Encoder Interface
            	DCD     PLL1_IRQHandler           			; 48: PLL1 Lock (USB PLL)
            	DCD     USBActivity_IRQHandler    			; 49: USB Activity interrupt to wakeup
            	DCD     CANActivity_IRQHandler    			; 50: CAN Activity interrupt to wakeup



; 芯片程序加密
            	IF      :LNOT::DEF:NO_CRP
            	AREA    |.ARM.__at_0x02FC|, CODE, READONLY
CRP_Key         DCD     0xFFFFFFFF
            	ENDIF


            	AREA    |.text|, CODE, READONLY				; 这个是干嘛的我也不知道,尴尬。。。




; 复位中断函数服务
Reset_Handler   PROC										; 定义子程序的伪指令,位于子程序的起始处
            	EXPORT  Reset_Handler             [WEAK]
            	IMPORT  SystemInit			 				; 声明函数   SystemInit(该函数在另外文件中定义的,声明后,本文件就可以调用该函数了)
            	IMPORT  __main
            	LDR     R0, =SystemInit						; 将SystemInit函数的首地址加载到寄存器R0中
            	BLX     R0									; 切换指令集,跳转到该地址运行,运行完该函数再返回到这
            	LDR     R0, =__main
            	BX      R0									; 切换指令集,跳转到该地址运行,不回来了
            	ENDP				  						; 定义子程序的伪指令,位于子程序的结束处




; 其他各种弱声明中断服务函数
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  WDT_IRQHandler            [WEAK]
            	EXPORT  TIMER0_IRQHandler         [WEAK]
            	EXPORT  TIMER1_IRQHandler         [WEAK]
            	EXPORT  TIMER2_IRQHandler         [WEAK]
            	EXPORT  TIMER3_IRQHandler         [WEAK]
            	EXPORT  UART0_IRQHandler          [WEAK]
            	EXPORT  UART1_IRQHandler          [WEAK]
            	EXPORT  UART2_IRQHandler          [WEAK]
            	EXPORT  UART3_IRQHandler          [WEAK]
            	EXPORT  PWM1_IRQHandler           [WEAK]
            	EXPORT  I2C0_IRQHandler           [WEAK]
            	EXPORT  I2C1_IRQHandler           [WEAK]
            	EXPORT  I2C2_IRQHandler           [WEAK]
            	EXPORT  SPI_IRQHandler            [WEAK]
            	EXPORT  SSP0_IRQHandler           [WEAK]
            	EXPORT  SSP1_IRQHandler           [WEAK]
            	EXPORT  PLL0_IRQHandler           [WEAK]
            	EXPORT  RTC_IRQHandler            [WEAK]
            	EXPORT  EINT0_IRQHandler          [WEAK]
            	EXPORT  EINT1_IRQHandler          [WEAK]
            	EXPORT  EINT2_IRQHandler          [WEAK]
            	EXPORT  EINT3_IRQHandler          [WEAK]
            	EXPORT  ADC_IRQHandler            [WEAK]
            	EXPORT  BOD_IRQHandler            [WEAK]
            	EXPORT  USB_IRQHandler            [WEAK]
            	EXPORT  CAN_IRQHandler            [WEAK]
            	EXPORT  DMA_IRQHandler            [WEAK]
            	EXPORT  I2S_IRQHandler            [WEAK]
            	EXPORT  ENET_IRQHandler           [WEAK]
            	EXPORT  RIT_IRQHandler            [WEAK]
            	EXPORT  MCPWM_IRQHandler          [WEAK]
            	EXPORT  QEI_IRQHandler            [WEAK]
            	EXPORT  PLL1_IRQHandler           [WEAK]
            	EXPORT  USBActivity_IRQHandler    [WEAK]
            	EXPORT  CANActivity_IRQHandler    [WEAK]

WDT_IRQHandler
TIMER0_IRQHandler
TIMER1_IRQHandler
TIMER2_IRQHandler
TIMER3_IRQHandler
UART0_IRQHandler
UART1_IRQHandler
UART2_IRQHandler
UART3_IRQHandler
PWM1_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
I2C2_IRQHandler
SPI_IRQHandler
SSP0_IRQHandler
SSP1_IRQHandler
PLL0_IRQHandler
RTC_IRQHandler
EINT0_IRQHandler
EINT1_IRQHandler
EINT2_IRQHandler
EINT3_IRQHandler
ADC_IRQHandler
BOD_IRQHandler
USB_IRQHandler
CAN_IRQHandler
DMA_IRQHandler
I2S_IRQHandler
ENET_IRQHandler
RIT_IRQHandler
MCPWM_IRQHandler
QEI_IRQHandler
PLL1_IRQHandler
USBActivity_IRQHandler
CANActivity_IRQHandler

           	 	B       . 									; 哈,这里有是个死循环,开了中断的外设一定要有自定义的中断服务函数没要不程序会搞死你
            	ENDP 
            	ALIGN										; 代码段和数据段以默认字节数对齐(默认字节数为一个字,即4个字节)




; 将堆栈地址传递给库函数
            	IF      :DEF:__MICROLIB 					; 如果定义了微库
            	EXPORT  __initial_sp
            	EXPORT  __heap_base
            	EXPORT  __heap_limit 
            	ELSE 										; 如果未勾选微库,则默认为KEIL C 库
            	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 									; 切换指令集,并跳转到LR寄存器所存储的地址
            	ALIGN 
            	ENDIF


            	END 

1. AREA伪指令:
用于定义一个代码段或数据段;
语法格式: AREA 段名 属性1 ,属性2 ,……
段名若以数字开头,则该段名需用“|”括起来,如:|1_test|。
常用的属性如下:
NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0;
CODE 属性:用于定义代码段,默认为READONLY;
DATA 属性:用于定义数据段,默认为READWRITE ;
READONLY 属性:指定本段为只读,代码段默认为READONLY;
READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE ;
ALIGN 属性:使用方式为ALIGN表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方,上述=3,即2^3=8,8字节对齐;
一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。

2. SPACE和DCD
功能类似,SPACE申请一片内存空间,DCD申请一个字(32bit)的内存空间。
区别在于,SPACE申请空间但不赋初值,DCD申请一个字的空间,并赋初值。

3. WEAK
官网解释:symbol is only imported into other sources if no other source exports an alternative symbol. If [WEAK] is used without symbol, all exported symbols are weak.
symbol is only imported into other sources if no other source exports an alternative symbol.
If [WEAK] is used without symbol, all exported symbols are weak.
如果没有其他来源导出替代符号,则仅将该符号导入其他来源。
如果在没有符号的情况下使用[WEAK],则所有导出的符号都是弱声明。

弱声明,即:如果用户定义了相同的函数,则此处函数失效而使用用户定义的中断服务函数。这样是为了防止用户使能了中断而没有中断服务函数,从而造成程序崩溃。假设使能了中断,而用户又没有定义中断服务函数则会进入默认中断,默认中断为死循环;
网上有人很形象的解释为:
就是告诉 链接器: "我略弱但我很绅士, 如果你在别处看到和我一样的符号实例.你就用它吧. 表管我, 求忽视!

死循环与程序崩溃不是一个概念,最近在调试期间经常进入HardFault_Handler中断里面,然后一直出不来,原来是在这发生死循环了。
为什么会出现死循环呢,因为该中断服务函数里面有句
B .
表示跳转到该行,然后就会一直在该行运行,即死循环了
下次遇到可以试着将该句去掉,看看会出现什么样的情况。

这篇文档是经过网上各种资料查阅以及自己领悟的成果,欢迎大家指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值