|
本帖最后由 FSL_TICS_ZJJ 于 2014-9-11 14:56 编辑
入手飞思卡尔,从启动文件学起吧,这是查阅官方帮助文档整理的版本,是已知目前最详细的启动文件介绍,结合了MAP文件和SCT文件
如有错误还请指正
在其他平台,启动文件功能基本一致,这里是我整理的MDK下的版本,修正了网上其它版本的一些错误,描述更详细
启动文件
- ;/*****************************************************************************
- ; * @file: startup_MKL02Z4.s
- ; * @purpose: CMSIS Cortex-M0plus Core Device Startup File for the
- ; * MKL02Z4
- ; * @version: 1.0
- ; * @date: 2012-10-4
- ; *
- ; * Copyright: 1997 - 2013 Freescale Semiconductor, Inc. All Rights Reserved.
- ;*
- ; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
- ; *
- ; *****************************************************************************/
- ; <h> Stack Configuration
- ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
- ; </h>
- Stack_Size EQU 0x00000100
- ;EQU定义符号指示Stack大小
-
- AREA STACK, NOINIT, READWRITE, ALIGN=3
- ;AREA 通知汇编器汇编一段新的代码或数据节(section)
- ;STACK 为AREA所定义的新的节的节名称(sectionname)
- ;NOINIT 指示这段数据节不初始化或初始化为0,以SPACE等指示的空间初始化为0,但不能初始化为其它
- ; 备注:即这段不能指定初始化值,如果不加NOINIT的话,MAP文件SPACE的数据类型为Data,为RW Data
- ; 如果加NOINIT的话,MAP文件SPACE的数据类型为Zero,为ZI Data
- ;READWRITE 指示该节类型为RW
- ;ALIGN=3 指示该节对齐到8字节boundary,即为双字地址
- ; 备注:在MAP文件中,可以发现是通过添加PAD类型的数据进行节的对齐
- ; PAD取何值可以指定
-
- Stack_Mem SPACE Stack_Size
- ;Stack_Mem 为一个标签(label),标签值为在当前节中的地址
- ;SPACE 指示(directive)一块内存(memory),这块内存所在节的特性由上面的AREA指定
- __initial_sp
- ;__initial_sp 为上面SPACE块的顶端地址+1,即说明堆栈的初始值为顶端地址,堆栈是向下生长的满栈
- ; 备注:因为CM的入栈操作是,*(--R13)=R0类似的一种方式,R13指向最后的数据
- ; <h> Heap Configuration
- ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
- ; </h>
- Heap_Size EQU 0x00000100
- ;定义符号指示Heap大小
- AREA HEAP, NOINIT, READWRITE, ALIGN=3
- ;定义一个新的节,节名称为HEAP,其它与STACK相同
- ;EXPORT __heap_base
- __heap_base
- ;定义一个标签,指示HEAP的基地址,这个标签只用在使用MICROLIB时被EXPORT,即只有这时有效
- ;使用MICROLIB时,这个标签被EXPORT,类似于C语言中的extern,但只有当HEAP被使用的时候
- ; 才出现在MAP文件中,如在main()中可以这样来访问__heap_base
- ; void main(void)
- ; {
- ; extern int __heap_base;
- ; static int HEAPBASE; //定义静态变量,在内存中有固定的存储空间
- ; ......
- ; HEAPBASE = __heap_base; //读取HEAP的即地址,只在MICROLIB时有效
- ; ......
- ; }
- ;如果要在不使用MICROLIB时,读取__heap_base, 那只需要在__heap_base前添加EXPORT __heap_base
- Heap_Mem SPACE Heap_Size
- ;EXPORT Heap_Mem
- ;定义HEAP的内存段,标签为Heap_Mem,将Heap_Mem EXPORT之后,可以这样访问:
- ; extern int Heap_Mem;
- ; static int* pHEAPMEM;
- ; pHEAPMEM = (int*)Heap_Mem;
- __heap_limit
- ;定义一个标签,HEAP的地址范围为__heap_base ~ (__heap_limit - 1)
-
- ;这里结合MAP文件外插上几句
- ;1. 当:STACK 所在节属性为 AREA STACK, NOINIT, READWRITE, ALIGN=3
- ; HEAP 所在节属性为 AREA HEAP, NOINIT, READWRITE, ALIGN=3
- ; 时,MAP文件的执行时期RAM镜像为
- ; Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000268, Max: 0x00000c00, ABSOLUTE)
- ;
- ; Base Addr Size Type Attr Idx E Section Name Object
- ;
- ; 0x20000000 0x00000004 Data RW 4 .data system_mkl02z4.o
- ; 0x20000004 0x00000004 Data RW 61 .data blinky.o
- ; 0x20000008 0x00000060 Zero RW 139 .bss c_p.l(libspace.o)
- ; 0x20000068 0x00000100 Zero RW 48 HEAP startup_mkl02z4.o
- ; 0x20000168 0x00000100 Zero RW 47 STACK startup_mkl02z4.o
- ;
- ; 可见,在程序运行时,数据在内存中存放的顺序为有初始化的Data类型,和0初始化的Zero类型
- ; 此时,HEAP向上增长,STACK向下生长,二者的方向是相向的
- ; 全局变量,如果没有指定初始值,如static int gTestData; 是存放在.dada节,而不是.bss
- ;
- ;2. 当:STACK 所在节属性为 AREA STACK, READWRITE, ALIGN=3
- ; HEAP 所在节属性为 AREA HEAP, NOINIT, READWRITE, ALIGN=3
- ; 时,MAP文件的执行时期RAM镜像为
- ; Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000268, Max: 0x00000c00, ABSOLUTE)
- ;
- ; Base Addr Size Type Attr Idx E Section Name Object
- ;
- ; 0x20000000 0x00000004 Data RW 4 .data system_mkl02z4.o
- ; 0x20000004 0x00000004 Data RW 61 .data blinky.o
- ; 0x20000008 0x00000100 Data RW 47 STACK startup_mkl02z4.o
- ; 0x20000108 0x00000060 Zero RW 139 .bss c_p.l(libspace.o)
- ; 0x20000168 0x00000100 Zero RW 48 HEAP startup_mkl02z4.o
- ;
- ; 此时HEAP向上增长,STACK向下生长,二者的方向是相背的
- ; 同时可以看出,不用NOINIT修饰时,STACK的数据类型为Data,是一种RW Type,否则是一种ZI Type
- ;
- ;部分细节看参见Linker User Guide: Type 2 image, one load region and non-contiguous execution regions
-
- PRESERVE8
- ;通知链接器(linker)当前文件是以堆栈8字节对齐,使用PRESERVE8的话,说明我们现在的文件堆栈是以8字节对齐的
- ;这样的话,这里的函数可以调用由REQUIRE8指示的文件的函数,而不引起错误,如LDRD and STRD指令,因为
- ;LDRD and STRD instructions (double-word transfers) only work correctly if the address they access
- ;is 8-byte aligned.
- THUMB
- ;通知编译器采用THUMB指令集
- ; Vector Table Mapped to Address 0 at Reset
- AREA RESET, DATA, READONLY
- ;指示当前节为RESET,节的属性为DATA(Contains data, not instructions),RO
- EXPORT __Vectors
- EXPORT __Vectors_End
- EXPORT __Vectors_Size
- ;全局变量__Vectors,__Vectors_End,和__Vectors_Size
- ;分散加载文件SCT为
- ; LR_IROM1 0x00000000 0x00008000 { ; load region size_region
- ; ER_IROM1 0x00000000 0x00008000 { ; load address = execution address
- ; *.o (RESET, +First) ; +First指示执行时RESET节置于最开始
- ; *(InRoot$Sections) ; InRoot$Sections指代所有必须放在根区域的节
- ; ; 如__main.o, __scatter*.o,
- ; ; __dc*.o, and * Region$Table
- ; .ANY (+RO) ; Read only的数据执行时在这里
- ; }
- ; RW_IRAM1 0x1FFFFC00 0x00000400 { ; RW data
- ; .ANY (+RW +ZI)
- ; }
- ; RW_IRAM2 0x20000000 0x00000C00 {
- ; .ANY (+RW +ZI)
- ; }
- ; }
- ;我们可以这样更改分散加载文件为
- ; LR_IROM1 0x00000000 0x00008000 { ; load region size_region
- ; ER_IROM1 0x00000000 0x00008000 { ; load address = execution address
- ; *.o (RESET, +First)
- ; *(InRoot$Sections)
- ; .ANY (+RO)
- ; }
- ; RW_IRAM1 0x1FFFFC00 0x00000400 { ; RW data
- ; .ANY (+ZI)
- ; }
- ; RW_IRAM2 0x20000000 0x00000C00 {
- ; .ANY (+RW)
- ; *.o (.bss)
- ; }
- ; }
- ;这样,执行时候的内存镜像变成这样子了,我们利用起来了两块RAM区的特点
- ; Execution Region RW_IRAM1 (Base: 0x1ffffc00, Size: 0x00000200, Max: 0x00000400, ABSOLUTE)
- ;
- ; Base Addr Size Type Attr Idx E Section Name Object
- ;
- ; 0x1ffffc00 0x00000100 Zero RW 48 HEAP startup_mkl02z4.o
- ; 0x1ffffd00 0x00000100 Zero RW 47 STACK startup_mkl02z4.o
- ;
- ;
- ; Execution Region RW_IRAM2 (Base: 0x20000000, Size: 0x00000068, Max: 0x00000c00, ABSOLUTE)
- ;
- ; Base Addr Size Type Attr Idx E Section Name Object
- ;
- ; 0x20000000 0x00000004 Data RW 4 .data system_mkl02z4.o
- ; 0x20000004 0x00000004 Data RW 61 .data blinky.o
- ; 0x20000008 0x00000060 Zero RW 139 .bss c_p.l(libspace.o)
- __Vectors DCD __initial_sp ; Top of Stack
- ; DCD 申请4字节的空间,存放数据
- ; 由于分散加载文件SCT中的*.o (RESET, +First)属性
- ; RESET节被放在了LR_IROM1的开始位置,即__initial_sp存放在0地址
- 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 Reserved16_IRQHandler ; Reserved interrupt 16
- DCD Reserved17_IRQHandler ; Reserved interrupt 17
- DCD Reserved18_IRQHandler ; Reserved interrupt 18
- DCD Reserved19_IRQHandler ; Reserved interrupt 19
- DCD Reserved20_IRQHandler ; Reserved interrupt 20
- DCD FTFA_IRQHandler ; FTFA command complete/read collision interrupt
- DCD LVD_LVW_IRQHandler ; Low Voltage Detect, Low Voltage Warning
- DCD Reserved23_IRQHandler ; Reserved interrupt 23
- DCD I2C0_IRQHandler ; I2C0 interrupt
- DCD I2C1_IRQHandler ; I2C1 interrupt
- DCD SPI0_IRQHandler ; SPI0 interrupt
- DCD Reserved27_IRQHandler ; Reserved interrupt 27
- DCD UART0_IRQHandler ; UART0 status/error interrupt
- DCD Reserved29_IRQHandler ; Reserved interrupt 29
- DCD Reserved30_IRQHandler ; Reserved interrupt 30
- 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 Reserved35_IRQHandler ; Reserved interrupt 35
- DCD Reserved36_IRQHandler ; Reserved interrupt 36
- DCD Reserved37_IRQHandler ; Reserved interrupt 37
- DCD Reserved38_IRQHandler ; Reserved interrupt 38
- DCD Reserved39_IRQHandler ; Reserved interrupt 39
- DCD Reserved40_IRQHandler ; Reserved interrupt 40
- DCD Reserved41_IRQHandler ; Reserved interrupt 41
- DCD Reserved42_IRQHandler ; Reserved interrupt 42
- DCD MCG_IRQHandler ; MCG interrupt
- DCD LPTimer_IRQHandler ; LPTimer interrupt
- DCD Reserved45_IRQHandler ; Reserved interrupt 45
- DCD PORTA_IRQHandler ; Port A interrupt
- DCD PORTB_IRQHandler ; Port B interrupt
- __Vectors_End
- ;这里__Vectors_End的值为0x000000c0 (在MAP文件里查看)
- __Vectors_Size EQU __Vectors_End - __Vectors ;计算中断向量表的大小
- ; 以下为Freescale特有的配置方式(我的理解,在ST中不是采用的这种配置方法)
- ; Flash配置区域在Flash的0x0000_0400开始的空间,一共16字节
- ; 关于Flash配置区域在帖子 http://www.amobbs.com/thread-5588189-1-1.html 中有描述
- ; 以下定义的变量值,在下面有采用,这边略过Flash配置字的含义,详见Reference Mannual
- ;
- ;
- ; <h> Flash Configuration
- ; <i> 16-byte flash configuration field that stores default protection settings (loaded on reset)
- ; <i> and security information that allows the MCU to restrict acces to the FTFL module.
- ; <h> Backdoor Comparison Key
- ; <o0> Backdoor Key 0 <0x0-0xFF:2>
- ; <o1> Backdoor Key 1 <0x0-0xFF:2>
- ; <o2> Backdoor Key 2 <0x0-0xFF:2>
- ; <o3> Backdoor Key 3 <0x0-0xFF:2>
- ; <o4> Backdoor Key 4 <0x0-0xFF:2>
- ; <o5> Backdoor Key 5 <0x0-0xFF:2>
- ; <o6> Backdoor Key 6 <0x0-0xFF:2>
- ; <o7> Backdoor Key 7 <0x0-0xFF:2>
- BackDoorK0 EQU 0xFF
- BackDoorK1 EQU 0xFF
- BackDoorK2 EQU 0xFF
- BackDoorK3 EQU 0xFF
- BackDoorK4 EQU 0xFF
- BackDoorK5 EQU 0xFF
- BackDoorK6 EQU 0xFF
- BackDoorK7 EQU 0xFF
- ; </h>
- ; <h> Program flash protection bytes (FPROT)
- ; <i> Each program flash region can be protected from program and erase operation by setting the associated PROT bit.
- ; <i> Each bit protects a 1/32 region of the program flash memory.
- ; <h> FPROT0
- ; <i> Program flash protection bytes
- ; <i> 1/32 - 8/32 region
- ; <o.0> FPROT0.0
- ; <o.1> FPROT0.1
- ; <o.2> FPROT0.2
- ; <o.3> FPROT0.3
- ; <o.4> FPROT0.4
- ; <o.5> FPROT0.5
- ; <o.6> FPROT0.6
- ; <o.7> FPROT0.7
- nFPROT0 EQU 0x00
- FPROT0 EQU nFPROT0:EOR:0xFF
- ; </h>
- ; <h> FPROT1
- ; <i> Program Flash Region Protect Register 1
- ; <i> 9/32 - 16/32 region
- ; <o.0> FPROT1.0
- ; <o.1> FPROT1.1
- ; <o.2> FPROT1.2
- ; <o.3> FPROT1.3
- ; <o.4> FPROT1.4
- ; <o.5> FPROT1.5
- ; <o.6> FPROT1.6
- ; <o.7> FPROT1.7
- nFPROT1 EQU 0x00
- FPROT1 EQU nFPROT1:EOR:0xFF
- ; </h>
- ; <h> FPROT2
- ; <i> Program Flash Region Protect Register 2
- ; <i> 17/32 - 24/32 region
- ; <o.0> FPROT2.0
- ; <o.1> FPROT2.1
- ; <o.2> FPROT2.2
- ; <o.3> FPROT2.3
- ; <o.4> FPROT2.4
- ; <o.5> FPROT2.5
- ; <o.6> FPROT2.6
- ; <o.7> FPROT2.7
- nFPROT2 EQU 0x00
- FPROT2 EQU nFPROT2:EOR:0xFF
- ; </h>
- ; <h> FPROT3
- ; <i> Program Flash Region Protect Register 3
- ; <i> 25/32 - 32/32 region
- ; <o.0> FPROT3.0
- ; <o.1> FPROT3.1
- ; <o.2> FPROT3.2
- ; <o.3> FPROT3.3
- ; <o.4> FPROT3.4
- ; <o.5> FPROT3.5
- ; <o.6> FPROT3.6
- ; <o.7> FPROT3.7
- nFPROT3 EQU 0x00
- FPROT3 EQU nFPROT3:EOR:0xFF
- ; </h>
- ; </h>
- ; </h>
- ; <h> Flash nonvolatile option byte (FOPT)
- ; <i> Allows the user to customize the operation of the MCU at boot time.
- ; <o.0> LPBOOT0
- ; <0=> Core and system clock divider (OUTDIV1) is 0x7 (divide by 8) or 0x3 (divide by 4)
- ; <1=> Core and system clock divider (OUTDIV1) is 0x1 (divide by 2) or 0x0 (divide by 1)
- ; <o.4> LPBOOT1
- ; <0=> Core and system clock divider (OUTDIV1) is 0x7 (divide by 8) or 0x1 (divide by 2)
- ; <1=> Core and system clock divider (OUTDIV1) is 0x3 (divide by 4) or 0x0 (divide by 1)
- ; <o.2> NMI_DIS
- ; <0=> NMI interrupts are always blocked
- ; <1=> NMI pin/interrupts reset default to enabled
- ; <o.3> RESET_PIN_CFG
- ; <0=> RESET pin is disabled following a POR and cannot be enabled as RESET function
- ; <1=> RESET pin is dedicated
- ; <o.3> FAST_INIT
- ; <0=> Slower initialization
- ; <1=> Fast Initialization
- FOPT EQU 0xFF
- ; </h>
- ; <h> Flash security byte (FSEC)
- ; <i> WARNING: If SEC field is configured as "MCU security status is secure" and MEEN field is configured as "Mass erase is disabled",
- ; <i> MCU's security status cannot be set back to unsecure state since Mass erase via the debugger is blocked !!!
- ; <o.0..1> SEC
- ; <2=> MCU security status is unsecure
- ; <3=> MCU security status is secure
- ; <i> Flash Security
- ; <i> This bits define the security state of the MCU.
- ; <o.2..3> FSLACC
- ; <2=> Freescale factory access denied
- ; <3=> Freescale factory access granted
- ; <i> Freescale Failure Analysis Access Code
- ; <i> This bits define the security state of the MCU.
- ; <o.4..5> MEEN
- ; <2=> Mass erase is disabled
- ; <3=> Mass erase is enabled
- ; <i> Mass Erase Enable Bits
- ; <i> Enables and disables mass erase capability of the FTFL module
- ; <o.6..7> KEYEN
- ; <2=> Backdoor key access enabled
- ; <3=> Backdoor key access disabled
- ; <i> Backdoor key Security Enable
- ; <i> These bits enable and disable backdoor key access to the FTFL module.
- FSEC EQU 0xFE
- ; </h>
- ;
- ; 在这里,定义了一个新的节,名称是.ARM,位于地址0x400,在MAP文件里是这样的
- ; ......
- ; 0x000003cc 0x00000030 Data RO 263 Region$Table anon$obj.o
- ; 0x000003fc 0x00000004 PAD
- ; 0x00000400 0x00000010 Code RO 50 .ARM.__at_0x400 startup_mkl02z4.o
- ; 0x00000410 0x00000174 Code RO 59 .text blinky.o
- ; 0x00000584 0x0000015a Code RO 93 .text c_p.l(aeabi_sdiv.o)
- ; ......
- ; 可见PAD补充字节空间,.ARM.__at_0x400放在了0x0400地址,而这些地址存放的数据,是CODE,RO类型
- ; 下面的DCB填充了这16个字节
- IF :LNOT::DEF:RAM_TARGET
- ; :DEF:A 语句,如果A定义,返回真,否则返回假
- ; :LNOT:A 语句,是对A的逻辑取反
- ; 结合上面的 IF,所以以下代码尽在RAM_TARGET没定义的时候会产生
- ; 如果在RAM中调试的话,应该定义RAM_TARGET,那样的话也就不需要FLASH配置字了
- ;
- AREA |.ARM.__at_0x400|, CODE, READONLY
- ; 定义一个节,存放配置数据,单片机复位后,FLASH控制器加载这些配置
- ;
- DCB BackDoorK0, BackDoorK1, BackDoorK2, BackDoorK3
- DCB BackDoorK4, BackDoorK5, BackDoorK6, BackDoorK7
- DCB FPROT0, FPROT1, FPROT2, FPROT3
- DCB FSEC, FOPT, 0xFF, 0xFF
- ENDIF
- ; 下面是程序端的开始
- AREA |.text|, CODE, READONLY
- ; AREA定义.text节存放代码,因为.text不是有效的变量名,所以加||限定
- ; Reset Handler
- Reset_Handler PROC
- ; 同FUNCTION,标记一个函数的开始
- EXPORT Reset_Handler [WEAK]
- ; 弱引用,通知链接器,其它文件中的同名函数的优先级高于这个函数,即只有当其它文件中无
- ; Reset_Handler函数时,Reset_Handler()才指向这里
- IMPORT SystemInit
- ; 告诉链接器到其它文件中查找SystemInit函数
- IMPORT __main
- ; 告诉链接器到其它文件中查找__main函数
- LDR R0, =SystemInit
- ; 执行SystemInit();
- BLX R0
- LDR R0, =__main
- ; 执行__main(); __main()调用main(),因而正常情况下不返回
- BX R0
- ENDP
- ; 标记函数的结束
- ; Dummy Exception Handlers (infinite loops which can be modified)
- ; 异常函数,弱引用,需要在其它文件中自定义相同名称的函数,以进行异常的处理
- ;
- NMI_Handler PROC
- EXPORT NMI_Handler [WEAK]
- B . ; 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
- Default_Handler PROC
- EXPORT Reserved16_IRQHandler [WEAK]
- EXPORT Reserved17_IRQHandler [WEAK]
- EXPORT Reserved18_IRQHandler [WEAK]
- EXPORT Reserved19_IRQHandler [WEAK]
- EXPORT Reserved20_IRQHandler [WEAK]
- EXPORT FTFA_IRQHandler [WEAK]
- EXPORT LVD_LVW_IRQHandler [WEAK]
- EXPORT Reserved23_IRQHandler [WEAK]
- EXPORT I2C0_IRQHandler [WEAK]
- EXPORT I2C1_IRQHandler [WEAK]
- EXPORT SPI0_IRQHandler [WEAK]
- EXPORT Reserved27_IRQHandler [WEAK]
- EXPORT UART0_IRQHandler [WEAK]
- EXPORT Reserved29_IRQHandler [WEAK]
- EXPORT Reserved30_IRQHandler [WEAK]
- EXPORT ADC0_IRQHandler [WEAK]
- EXPORT CMP0_IRQHandler [WEAK]
- EXPORT TPM0_IRQHandler [WEAK]
- EXPORT TPM1_IRQHandler [WEAK]
- EXPORT Reserved35_IRQHandler [WEAK]
- EXPORT Reserved36_IRQHandler [WEAK]
- EXPORT Reserved37_IRQHandler [WEAK]
- EXPORT Reserved38_IRQHandler [WEAK]
- EXPORT Reserved39_IRQHandler [WEAK]
- EXPORT Reserved40_IRQHandler [WEAK]
- EXPORT Reserved41_IRQHandler [WEAK]
- EXPORT Reserved42_IRQHandler [WEAK]
- EXPORT MCG_IRQHandler [WEAK]
- EXPORT LPTimer_IRQHandler [WEAK]
- EXPORT Reserved45_IRQHandler [WEAK]
- EXPORT PORTA_IRQHandler [WEAK]
- EXPORT PORTB_IRQHandler [WEAK]
- EXPORT DefaultISR [WEAK]
- Reserved16_IRQHandler
- Reserved17_IRQHandler
- Reserved18_IRQHandler
- Reserved19_IRQHandler
- Reserved20_IRQHandler
- FTFA_IRQHandler
- LVD_LVW_IRQHandler
- Reserved23_IRQHandler
- I2C0_IRQHandler
- I2C1_IRQHandler
- SPI0_IRQHandler
- Reserved27_IRQHandler
- UART0_IRQHandler
- Reserved29_IRQHandler
- Reserved30_IRQHandler
- ADC0_IRQHandler
- CMP0_IRQHandler
- TPM0_IRQHandler
- TPM1_IRQHandler
- Reserved35_IRQHandler
- Reserved36_IRQHandler
- Reserved37_IRQHandler
- Reserved38_IRQHandler
- Reserved39_IRQHandler
- Reserved40_IRQHandler
- Reserved41_IRQHandler
- Reserved42_IRQHandler
- MCG_IRQHandler
- LPTimer_IRQHandler
- Reserved45_IRQHandler
- PORTA_IRQHandler
- PORTB_IRQHandler
- DefaultISR
- ;上面这些函数的地址都是一样的,即标号的值都相同,但都是弱引用
- B .
- ENDP
- ALIGN
- ; ALIGN不指定参数时,将当前地址对起到4字节,填0或NOP,或其它给定值
- ; User Initial Stack & Heap
- IF :DEF:__MICROLIB
- ; 如果定义使用MICROLIB,则将下面的标号声明为全局变量,供MICROLIB使用
- ;
- EXPORT __initial_sp
- EXPORT __heap_base
- EXPORT __heap_limit
- ELSE
- IMPORT __use_two_region_memory
- ; 指定存储器模式为双区模式
- ; 单区模型:(r0, r1)是单个堆栈和堆区,r1大于r0,忽略r2和r3
- ; 堆和栈共用一块内存区域
- ; 双区模型:(r0, r2)是初始堆,(r3, r1)是初始栈
- ; 堆和栈分别指定了单独的内存区域
- ;
- EXPORT __user_initial_stackheap
- ; 声明一个全局标号 __user_initial_stackheap作为函数使用
- __user_initial_stackheap
- ; C标准库调用__user_initial_stackheap()函数,获得堆栈信息
- ; 这里没有使用PROC标记
- ;
- 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
复制代码
里面我有一个没搞懂的地方,就是最后的__user_initial_stackheap为什么不加PROC标记
KL02官方Keil MDK例程文件
附图1:堆栈分配
附图2:加载镜像和执行镜像
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|