原文在此:http://www.cnblogs.com/mddblog/p/4920063.html

概述

  在嵌入式系统中,启动文件是整个系统非常关键的部分,它会进行一些底层的初始化,构建程序运行必要的环境,比如堆栈初始化,变量初始化等。如果启动文件出现错误,则整个系统就跑不起来,因此研究启动文件非常必要。

  在keil中,启动文件由汇编代码编写,一般命名为startup_xxx.s,xxx为支持的某种芯片,比如可以是lpc15xx(NXP的LPC15xx系列)、MK60D10(飞思卡尔)、stm32f10x(意法半导体stm32f10x系列)等Cortext-M0/M3/M4内核芯片。它们的代码格式非常相近,根据启动文件代码由上到下的编写顺序.

可以将其分为以下5个典型部分:

  1.堆栈空间定义;

  2.存放中断向量表;

  3.复位中断函数(Reset_Handler);

  4.其它中断异常服务函数,以及弱[WEAK]声明;

  5.将堆栈地址传递给库函数,利用库函数初始化堆栈,和库函数自身初始化。

5个部分具体说明如下:

1.堆栈空间定义

  如下图所示,定义了栈大小Stack_Size = 0X200,即512字节;堆大小Heap_Size = 0X100,256字节。还定义了三个标号:__initial_sp(栈顶)、__heap_base(堆起始地址)和__heap_limit(堆终止地址),它们的空间由SPACE关键字来申请,并记作Stack_Mem和Heap_Mem。

  通过这些我们可以很容易的知道堆栈的大小,但是它们的绝对地址或者说基地址仅仅从这里是得不到的。编译器编译完工程后,根据生成.bss段(比如未初始化的全局变量)和.data段(比如初始化的全局变量)的大小以及RAM的起始地址,来计算堆栈的基地址。

举个例子:

  一个芯片的RAM起始地址为0x0200_0000,RAM大小为0x500字节,程序编译后.bss段为0x100个字节,.data段为0x100个字节。堆栈大小定义如上图。则:

  A:堆起始地址  __heap_base==Heap_Mem==0x0200_0200;

  B:堆终止地址即栈底 __heap_limit==Stack_Mem==0x0200_0300;

  C:栈顶地址 __initial_sp==0x0200_0500(栈是向下生长,栈顶处于RAM最大地址处)。

  其实,我可以在.map文件中查看堆栈的大小和基地址,如下图所示:

 

2.存放中断向量表

  在启动代码中,会见到许多由DCD申请空间存放的一个个函数入口,即中断向量表,如下图所示,只列出了部分。

  关键字DCD代表申请一个字的空间,后面的函数名即为中断服务函数入口地址。另外中断向量表一般存放在Flash 0地址。

  另外,对于NXP微控制器,均实现了芯片的加密,加密的设置在向量表的结尾处,具体地址为0x02FC处。通过在此地址存放不同的值实现是否加密或者加密的等级。加密分为三个等级,CRP1:0x12345678;CRP2:0x87654321;CRP3:0x43218765。至于每个等级的具体说明请参考芯片用户手册。下面说一下加密步骤,以CRP1为例:

  首先将下图中0xFFFFFFFF,修改为0x12345678。

  其次,图中IF    :LNOT::DEF:NOCRP表示如果没有定义宏NOCRP则执行下面的代码,那么必须保证汇编中没有定义NOCRP宏。即保证下图中Define:一栏中没有定义NOCRP即可。

3. 复位中断函数(Reset_Handler)

  程序上电后,首先加载SP和PC,ARM规定从0地址处加载SP,从偏移为4的地址(0x00000004)处加载PC。然后将程序控制权交给程序。我们知道0地址处存放__initial_sp,0x00000004地址处存放Reset_Handler,加载PC后,程序跳转到Reset_Handler开始运行。Reset_Handler函数体如下图所示:

  首先调用SystemInit函数来初始化系统的各种时钟,然后调用__main函数(由KEIL微库或者C库实现),在__main函数中:.data段数据的初始化->.bss段变量清零->设置堆栈指针->库函数初始化(比如常用的malloc函数)->如果必要会设置main函数的argc和argv两个参数->调用用户main函数->退出。

4.其它中断异常服务函数,以及弱[WEAK]声明

  如上图所示,这里的中断服务函数是弱声明的(由[WEAK]关键字标注)。所谓弱声明,即:如果用户定义了相同的函数则此处函数失效而使用用户定义的中断服务函数。这样是为了防止用户使能了中断而没有中断服务函数,从而造成程序崩溃。假设使能了中断,而用户又没有定义中断服务函数则会进入默认中断,如下图所示,默认中断为死循环(死循环与程序崩溃不是一个概念)。

5.将堆栈地址传递给库函数

  第三步骤中,调用__main函数,然后__main调用库函数初始化堆栈,但库函数并不知道堆栈的大小,因此我们需要告诉它,具体做法就是传递参数或声明标号。

  下图为具体做法,可以看到第一行为:

IF      :DEF:__MICROLIB

  是条件编译选项,如果定义__MICROLIB,则编译图中红线上面部分,否则编译红线下面部分。那么就分2种情况。

  2种情况的选择可以如下实现:

如果勾选【Options for Target】->【Target】->【Use MicroLIB】,如下图所示。即使用微库,则__MICROLIB会被定义,编译器编译红线以上代码。用EXPORT声明 __initial_sp、__heap_base和__heap_limit。

   如果不勾选【Use MicroLIB】,则缺省使用KEIL C库,上图红线以下会参与编译,KEIL C库函数会调用__user_initial_stackheap,通过R0~R3将堆栈以参数形式传递给KEIL C库。

KEIL中启动文件详解(汇编语言)的更多相关文章

  1. Liunx中fstab文件详解

    Liunx中fstab文件详解 /etc/fstab是用来存放文件系统的静态信息的文件.位于/etc/目录下,可以用命令less /etc/fstab 来查看,如果要修改的话,则用命令 vi /etc ...

  2. 【转】linux中inittab文件详解

    原文网址:http://www.2cto.com/os/201108/98426.html linux中inittab文件详解 init的进程号是1(ps -aux | less),从这一点就能看出, ...

  3. 第14章 启动文件详解—零死角玩转STM32-F429系列

    第14章     启动文件详解 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege ...

  4. STM32启动文件详解

    启动文件使用的 ARM 汇编指令汇总 启动程序源码注释(点此下载) 1. Stack—栈 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE ...

  5. 单片机STM32的启动文件详解--学习笔记

    启动文件简介 启动文件由汇编编写,是系统上电复位后第一个执行的程序.主要做了以下工作: 1.初始化堆栈指针SP=_initial_sp 2.初始化PC 指针=Reset_Handler 3.初始化中断 ...

  6. (转)stm32启动文件详解

    在<<STM32不完全手册里面>>,用的是STM32F103RBT6,所有的例程都采用了一个叫STM32F10x.s的启动文件,里面定义了STM32的堆栈大小以及各种中断的名字 ...

  7. linux中inittab文件详解

    init的进程号是1(ps -aux | less),从这一点就能看出,init进程是系统所有进程的起点,Linux在完成核内引导以后,就开始运行init程序. init程序需要读取配置文件/etc/ ...

  8. (转) eclipse项目中.classpath文件详解

    背景:对于java项目中.classpath文件中的相关定义一直不是很了解,有必要进行深入的学习. 1 前言 在使用eclipse或者myeclipse进行Java项目开发的时候,每个project( ...

  9. windows中.msc文件详解

    msc是Microsoft Management Console的缩写.其实是一种可执行程序类型,可.exe类似.一般可以通过直接双击.msc文件或者在windows的运行中输入相应的文件名来启动. ...

随机推荐

  1. PHP之验证码的实现

    简单的用PHP实现验证码: ?php /** *制作验证码 *1.启动session *2.设定标头 *3.创建画布 *4.创建颜色 *5.创建随机数并放到画布上 *6.将得到的若干随机数放入sess ...

  2. APP接口自动化测试JAVA+TestNG(二)之TestNG简介与基础实例

    前言 继上篇环境篇后,本篇主要对TestNG进行介绍,给出最最基础的两个实例,通过本文后,学会并掌握TestNG测试用例的编写与运行,以及生成美化后的报告.下一篇为HTTP接口实战(国家气象局接口自动 ...

  3. OpenCV2:Mat

    1.Mat基础 在计算机内存中,数字图像是已矩阵的形式保存的.OpenCV2中,数据结构Mat是保存图像像素信息的矩阵,它主要包含两部分:矩阵头和一个指向像素数据的矩阵指针. 矩阵头主要包含,矩阵尺寸 ...

  4. Sublime插件支持Sass编译和Babel解析ES6 & .sublime-build文件初探

    用Sublime Text蛮久了,配置配来配去的,每次换电脑都得重头再配过,奈何人老了脑子不中用了,得好好整理一些,下次换电脑就有得参考了.. 同事说,他的WebStorm简直太方便,自身集成了很多方 ...

  5. 3.Code-First 约定(EF Code-First系列)

    前面,我们已经了解了Code-First利用领域类,怎么为我们创建数据库的简单示例.现在我们来学习一下Code-First约定吧. 什么是约定 约定说白了,就是基于一套规矩办事,这里就是基于你定义好的 ...

  6. MapReduce Shuffle过程

    MapReduce Shuffle 过程详解 一.MapReduce Shuffle过程 1. Map Shuffle过程 2. Reduce Shuffle过程 二.Map Shuffle过程 1. ...

  7. 【原创】HDFS介绍

    一.            HDFS简介 1.    HDFS全称 Hadoop Distributed FileSystem,Hadoop分布式文件系统. Hadoop有一个抽象文件系统的概念,Ha ...

  8. Xamarin.Android之给我们的应用加点过渡效果

    零.前言 试想一下,我们的应用正在请求一些数据,假设网络不是很好,要花比较长的时间等待,这个时候界面什么反应也没有, 一动不动,用户可能就会认为应用挂掉了,这么久都没反应的,说不定下一分钟用户就把它卸 ...

  9. 转:sublime text注册码

    —– BEGIN LICENSE —–Michael BarnesSingle User LicenseEA7E-8213858A353C41 872A0D5C DF9B2950 AFF6F667C4 ...

  10. jquery easyui使用(一)······可折叠面板的布局,手风琴

    <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...