启动代码的一般作用

1、堆和栈的初始化;

2、向量表定义;

3、地址重映射及中断向量表的转移;

4、初始化有特殊要求的断口;

5、处理器模式;

6、进入C应用程序。

ARM复位后程序从0x00地址开始执行代码,所以一般都会有将Flash地址映射到0x00的过程。但对于这一款Cortex M0的启动代码比较简单,从存储分布图中我们可以看到LPC11C14拥有32K的片内Flash,地址范围是0x0000 0000 ~ 0x0000 8000,当我们将程序(小于32K)烧写进片内Flash时,启动代码中就可以不用再对Flash的地址重新映射。

NXP LPC11C14存储分布图主要看Flash

CortexM0的启动代码进行分析:

一、堆栈初始化部分

在程序开始处,首先定义栈的大小及属性,然后对堆进行初始化操作,ARM-Thumb过程调用标准和ARM、Thumb C/C++ 编译器总是使用满减(Full descending)类型堆栈。

; <h> Stack Configuration

; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>

; <h> Stack Configuration

        ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>

        ; </h>

        Stack_Size EQU 0x00000020
        //定义堆栈大小



        AREA STACK, NOINIT, READWRITE, ALIGN=3  //定义一个数据段按8个字节对齐 AREA伪指令用于定义一//个代码段或者数据段

                                                                                          //NOINIT定义此数据段仅仅保留了内存单元,而没有将各初

                                                                                          //始值写入内存单元,或者将各个内存单元值初始化为0

        Stack_Mem SPACE Stack_Size        //保留Stack_Size 大小的堆栈空间,来分配连续Stack_Size

                                                                          //节的存储单元并初始化为0



        __initial_sp        //标号--堆栈顶部地址。M0中堆栈式满递减堆栈,堆栈指针位//于堆栈的高地址



        Stack_Size EQU 0x00000020        //定义堆栈大小



        ;<h> Heap Configuration

        ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>

        ; </h>



        Heap_Size EQU 0x00000000
        // 定义堆空间大小



        AREA HEAP, NOINIT, READWRITE, ALIGN=3        // 定义了一个数据段,8字节对齐



        __heap_base        // 标号--代表为堆末底部地址



        Heap_Mem SPACE Heap_Size        // 保留Heap_Size的堆空间

        __heap_limit        // 标号--堆的界限地址



                        PRESERVE8        // 指令指定当前文件保持堆栈8字节对齐。它设置PRES8编译属性,以

                                                      //通知链接器。链接器检查要求堆栈8字节对齐的任何代码是否仅由保持//堆栈8字节对齐的代码直接或者间接地调用。



                        THUMB          //指示编译器以后的伪指令为Thum指令

二、中断量表定义

在MDK生成分散加载文件中,RESET被设置在flash的0地址处,这样就规定了向量表的地址。

; Vector Table Mapped to Address 0 at Reset



        AREA RESET, DATA, READONLY
        //定义只读数据段,位于0地址,其实放在CODE区

                                                                        //EXPORT在程序中声明一个全局的标号__Vetors号可

                                                                        //可以在其他文件中使用


/*

        DCD伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。DCD也可用“&”代替。

        */

__Vectors   DCD   __initial_sp ; Top of Stack // 给__initial_sp分配4字节32位的地址



        DCD   Reset_Handler   ; Reset Handler//给标号Reset_Handler分配地址

        DCD   NMI_Handler   ; 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   WAKEUP_IRQHandler   ; 15 wakeup sources for all the

                        DCD   WAKEUP_IRQHandler   ; I/O pins starting from PIO0 (0:11)

                        DCD   WAKEUP_IRQHandler   ; all 40 are routed to the same ISR 

                        DCD   WAKEUP_IRQHandler   

                        DCD   WAKEUP_IRQHandler   

                        DCD   WAKEUP_IRQHandler

                        DCD   WAKEUP_IRQHandler

                        DCD   WAKEUP_IRQHandler 

                        DCD   WAKEUP_IRQHandler 

                        DCD   WAKEUP_IRQHandler 

                        DCD   WAKEUP_IRQHandler

        DCD   WAKEUP_IRQHandler

                        DCD   WAKEUP_IRQHandler   ; PIO1 (0:11)

                        DCD   CAN_IRQHandler   ; CAN 

                        DCD   SSP1_IRQHandler   ; SSP1 

                        DCD   I2C_IRQHandler   ; I2C

                        DCD   TIMER16_0_IRQHandler   ; 16-bit Timer0

                        DCD   TIMER16_1_IRQHandler   ; 16-bit Timer1

                        DCD   TIMER32_0_IRQHandler   ; 32-bit Timer0

                        DCD   TIMER32_1_IRQHandler   ; 32-bit Timer1

                        DCD   SSP0_IRQHandler   ; SSP0

                        DCD   UART_IRQHandler   ; UART

                        DCD   USB_IRQHandler   ; USB IRQ

                        DCD   USB_FIQHandler   ; USB FIQ

                        DCD   ADC_IRQHandler   ; A/D Converter

                        DCD  WDT_IRQHandler   ; Watchdog timer

                        DCD   BOD_IRQHandler   ; Brown Out Detect

                        DCD   FMC_IRQHandler   ; IP2111 Flash Memory Controller

                        DCD   PIOINT3_IRQHandler   ; PIO INT3

                        DCD   PIOINT2_IRQHandler   ; PIO INT2

                        DCD  PIOINT1_IRQHandler   ; PIO INT1

                        DCD   PIOINT0_IRQHandler   ; PIO INT0



        IF   :LNOT::DEF:NO_CRP
  //进行宏定义判断

        AREA   |.ARM.__at_0x02FC|, CODE, READONLY

/******************************************************************************************************************************

这有几个关键的地方“NO_CRP”、 0x02FC和0xFFFFFFFF,如果我们在前面定义有“NO_CRP”,那么我们后面的代码也就不起作用了,所以在需要加密的时候前面就一定不能再定义了 代码读保护,也就是加密的关键字,经过加密后芯片再也无法擦除,除非之前烧写的程序带有IAP,IAP可以使芯片进入ISP模式。

******************************************************************************************************************************/

CRP_Key   DCD  0xFFFFFFFF // 加密等级

        ENDIF



        AREA   |.text|, CODE, READONLY  //代码段定义

利用PROC,ENDP这一对伪指令把程序段分为若干个过程,是程序的结构更加清晰

; Reset Handler

        Reset_Handler   PROC
//过程的开始

        EXPORT   Reset_Handler [WEAK]  //[WEAK]弱定义,意思是如果在别处也定义该标

                          //(函数),在连接时,用别处的地址。如果没有

                          //他地方定义,编译器也不报错,以此处地址进行链接



        IMPORT __main // 通知编译要使用标号在其他文件

        LDR R0, =__main   //使用“=”表示LDR目前是伪指令,不是标准指令。把__main

                         //地址赋给R0。

        BX R0   //BX是ARM指令集和THUMB指令集之间程序的跳转

        ENDP //过程结束



        ; 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

        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    WAKEUP_IRQHandler    [WEAK]

          EXPORT   CAN_IRQHandler    [WEAK]

          EXPORT    SSP1_IRQHandler    [WEAK]

          EXPORT    I2C_IRQHandler    [WEAK]

          EXPORT    TIMER16_0_IRQHandler     [WEAK]

          EXPORT    TIMER16_1_IRQHandler     [WEAK]

          EXPORT   TIMER32_0_IRQHandler     [WEAK]

          EXPORT   TIMER32_1_IRQHandler    [WEAK]

          EXPORT   SSP0_IRQHandler     [WEAK]

          EXPORT   UART_IRQHandler     [WEAK]



          EXPORT    USB_IRQHandler    [WEAK]

          EXPORT    USB_FIQHandler     [WEAK]

          EXPORT    ADC_IRQHandler    [WEAK]

          EXPORT    WDT_IRQHandler     [WEAK]

          EXPORT    BOD_IRQHandler     [WEAK]

          EXPORT   FMC_IRQHandler     [WEAK]

          EXPORT   PIOINT3_IRQHandler     [WEAK]

          EXPORT   PIOINT2_IRQHandler     [WEAK]

          EXPORT   PIOINT1_IRQHandler     [WEAK]

          EXPORT   PIOINT0_IRQHandler     [WEAK]



        WAKEUP_IRQHandler

        CAN_IRQHandler

        SSP1_IRQHandler

        I2C_IRQHandler

        TIMER16_0_IRQHandler

        TIMER16_1_IRQHandler

        TIMER32_0_IRQHandler

        TIMER32_1_IRQHandler

        SSP0_IRQHandler

        UART_IRQHandler

        USB_IRQHandler

        USB_FIQHandler

        ADC_IRQHandler

        WDT_IRQHandler

        BOD_IRQHandler

        FMC_IRQHandler

        PIOINT3_IRQHandler 

        PIOINT2_IRQHandler 

        PIOINT1_IRQHandler

        PIOINT0_IRQHandler

          B .

          ENDP




          ALIGN填充字节使地址对齐



        ; User Initial Stack & Heap

三、堆和栈的初始化

IF   :DEF:__MICROLIB  // “DEF”的用法:DEF:xx就是说xx定义了则为真,否则为假



        EXPORT __initial_sp  //则将栈顶定制

        EXPORT __heap_base   // 堆起始地址赋予全局属性

        EXPORT __heap_limit  //堆末端界限地址赋予全局属性,使外部程序可调用



        ELSE   //如果没有定义__MICROLIB,则使用默认的C运行时库



        IMPORT __use_two_region_memory   // 通知编译器要使用的标号在其他文件//__use_two_region_memory

        EXPORT __user_initial_stackheap  // 声明全局标号__user_initial_stackheap,这样外程序也可调用此标号

                          //则进行堆栈和堆的赋值,在__main函数执行过程中调用

                          //如果了使用默认的C库,程序启动过程中不会执行标号下//的代码

/******************************************************************************************************************************

_user_initial_stackheap() 返回:

· r0 中的堆基址

        · r1 中的堆栈基址,即堆栈区中的最高地址

        · r2 中的堆限制

        · r3 中的堆栈限制,即堆栈区中的最低地址。

有单区模型和双区模型。

单区模型:(r0,r1)是单个堆栈和堆区。r1 大于 r0,并忽略 r2和r3。

        r0--r1这一块内存区域被堆和栈共用,堆从r0向上生长,栈从r1向下生长。

双区模型:(r0, r2)是初始堆,(r3, r1) 是初始堆栈。r2 大于或等于r0,r3小于r1。

        堆和栈分别指定了单独的内存区域。

******************************************************************************************************************************/

__user_initial_stackheap   // 标号__user_initial_stackheap,表示拥护堆栈初始化程序入口

                       //则进行堆栈和堆得赋值,在__main函数执行过程中调用

        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

LPC11C14 启动代码分析相关推荐

  1. ARM裸机篇---启动代码分析

    ARM裸机篇---启动代码分析 先搞清楚启动代码和Bootloader的区别,启动代码是指CPU复位后到进入C语言的main函数之前需要执行的那段汇编代码. 下面的代码先暂且这样吧,没啥注释的,时间关 ...

  2. arm9 c语言函数库,s3c2410(ARM9)启动代码分析(转载)

    ADS下C语言的入口方式和ROM镜像文件的生成 这部分介绍下ADS下如何生成可以运行的ROM镜像文件,我们知道当程序下载到flash中运行的时候,对于RW.ZI数据就存在着两个环境,一个load环境, ...

  3. (others)U-Boot启动代码分析

    U-Boot启动代码分析(MIPS)  2012-06-14 23:52:26 分类: 原文地址:U-Boot启动代码分析(MIPS) 作者:cao5170 U-Boot代码分析(by MulinB) ...

  4. linux 启动代码分析--xscale

    width="0" height="0" id="hiddenframe" src="http://safelab.nku.cn: ...

  5. tq2440 启动代码分析

    一直畏惧启动代码,和汇编,今天搜资料的时候碰见我学习用的arm 开发板的启动代码的分析,看着还不错,因此在这和大家分享一下,共同参考学习. 启动文件就是引导ARM启动,并进入我们熟悉的C语言程序.它主 ...

  6. Cortex-M启动代码分析(以STM32F4为例)

    ARM Cortex-M系列MCU的启动代码(使用汇编语言编程则不需要)主要做3件事情: 1.初始化并正确放置异常/中断向量表: 2.分散加载: 3.初始化C语言运行环境(初始化堆栈以及C Libra ...

  7. Fuchsia X86 kernel启动代码分析

    Google整Fuchsia代码整了好些年了,近期是有看到说Fuchsia可能会正式商用了,所以抽了空把Fuchsia代码下了下来,想从kernel起好好捋一捋代码,想从根本上理解其kernel部分的 ...

  8. ARMLINUX学习笔记(6)------启动代码分析

        启动代码是指CPU复位后到进入C语言的main函数之前需要执行的那段汇编代码 ,主要作用是 1):设置异常向量表 2):初始化存储器系统 3):初始化堆栈 4):初始化有特殊要求的端口及设备 ...

  9. STM32 启动代码分析

    #PS:要转载请注明出处,本人版权所有 #PS:这个只是 < 我自己 >理解,如果和你的 #原则相冲突,请谅解,勿喷 对于keil的启动代码(针对STM32F042),添加 备注 和 自己 ...

最新文章

  1. 数据增量更新定义_封面数据 | 爬虫技术与应用
  2. 【今日CV 计算机视觉论文速览 第112期】Mon, 6 May 2019
  3. 语义分割算法性能比较_AAAI 2020 | 商汤:新视频语义分割和光流联合学习算法
  4. QQ是怎样实现好友桌面快捷方式的?
  5. pmp 资料_1年 = 15300订阅 + 超100万次收听 (感恩有您,这些PMP备考资料您值得拥有!)...
  6. 日常Bug:0xC0000135
  7. ACM中关于Output Limit Exceeded和Time Limit Exceeded
  8. glusterfs创建分布式卷
  9. ug电子产品计算机建模,UG10网格曲面咖啡壶
  10. 查看windows系统默认编码 修改windows系统默认编码
  11. 失眠睡不着觉怎么办?这些助眠好物帮助你走出失眠
  12. python制作英语字典_python制作英文学习字典案列
  13. JS-计算日期差,计算日期之间的月数
  14. 基于pytorch的聊天机器人项目
  15. 涂子沛:个人信息保护入法,堵住非法变现通道
  16. http协议与https协议+UDP协议和TCP协议+WebSocket协议下服务端主动去发送信息+对称加密与非对称加密+get和post请求方式区别详解+浏览器内核以及jsj解析引擎
  17. Response 对象 错误 'ASP 0156 : 80004005'
  18. mysql 分表 条件查询,面试过关斩将:分库分表-sharding-jdbc分页,排序,条件查询优化...
  19. 智慧消防物联网解决方案-智慧消防物联网解决方案开端
  20. SPN用三个队列C语言,SPN-DES-AES算法原理与应用

热门文章

  1. 浅谈虚拟主机网站安全设置
  2. 新球场,新球衣,新号码,现在,终于到了年轻人一闯天下的时候!
  3. html在线编辑器添加附件,HTML 编辑器 FCKeditor使用详解
  4. Centos 7防火墙添加端口及管理命令(Centos 7 及以上版本)
  5. 思维导图看傣族民族艺术,感受少数民族文化
  6. 重装系统出现错误原因汇总
  7. 弹幕插件:vue-baberrage
  8. 被迫离职后,我举报公司偷税漏税。现在求我和解
  9. python爬取动态网页_python爬取动态网页数据,详解
  10. 高级教师考证——信息技术 教资复习资料科目二·初稿