;/*****************************************************************************
; * @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>