bootloader程序分析arm启动分析
arm启动原理及代码分析
初始化应用程序的执行环境
• Elf文件的类型:可执行文件、可重定位文 件、共享库object(又叫做共享库)文件。 • Elf文件的功能: 1、用作链接器的输入生成可执行的映像 文件 2、可装载到内存里运行,完成特定功能 的文件。
elf文件的物理结构
• • • • Elf文件头 Section: .text .data .bss .symtab Program header 可重定位文件与可执行文件的区别: 区与段的概念 program header
Section Header Table
可执行映像文件的逻辑结构
Output 输出段
Output 输出段 域 Output 输出段
装载域和运行域
• 域又组成什么呢?当然就是组成可执行文 件了,一个映像文件可以包含一到多个域。 与看起来有些多余,实际上更为重要的是 用域来描述输出区运行前和运行时在存储 系统上的位置。所以,域分为装载域和运 行域。装载域描述运行前输出段在rom/ram 中的分布状态,运行域描述运行时输出段 在rom/ram中的分布状态
• Nand flash(不可作为bootrom的存储器)
Boot相关硬件
Boot的主要功能
• • • • • 建立异常向量表 初始化中断 初始化硬件设备 初始化应用程序执行环境 跳转到主应用程序
0x00 0x04 异 常 中 断 向 量 表 的 建 立 0x08 0x0c 0x10 0x14 0x18
Section Header Table Hello.o
可执行映像文件的逻辑结构
由几个可重定位的目标文件的相同属性区组 成了可执行映像的段,那么段有组成什么? 在逻辑结构里,段组成了更大的组织:域
输入区ro 输入区rw
arm版本linux系统的启动流程
arm版本linux系统的启动流程ARM架构是一种常见的处理器架构,被广泛应用于嵌入式设备和移动设备中。
在ARM版本的Linux系统中,启动流程是非常重要的,它决定了系统如何从开机到正常运行。
本文将详细介绍ARM版本Linux系统的启动流程。
一、引导加载程序(Bootloader)引导加载程序是系统启动的第一阶段,它位于系统的固化存储器中,比如ROM或Flash。
在ARM版本的Linux系统中,常用的引导加载程序有U-Boot和GRUB等。
引导加载程序的主要功能是加载内核镜像到内存中,并将控制权转交给内核。
二、内核初始化引导加载程序将内核镜像加载到内存后,控制权被转交给内核。
内核初始化是系统启动的第二阶段,它主要完成以下几个步骤:1. 设置异常向量表:ARM架构中,异常是指硬件产生的中断或故障,比如系统调用、中断请求等。
内核需要设置异常向量表,以便正确处理异常。
2. 初始化处理器:内核对处理器进行初始化,包括设置页表、启用缓存、初始化中断控制器等。
3. 启动第一个进程:内核创建第一个用户进程(一般是init进程),并将控制权转交给它。
init进程是系统中所有其他进程的父进程,负责系统的初始化工作。
三、设备树(Device Tree)设备树是ARM版本Linux系统中的一种机制,用于描述硬件设备的相关信息。
在内核初始化过程中,内核会解析设备树,并建立设备树对象,以便后续的设备驱动程序使用。
设备树描述了硬件设备的类型、地址、中断等信息,以及设备之间的连接关系。
它使得内核能够在运行时自动识别和配置硬件设备,大大提高了系统的可移植性和灵活性。
四、启动初始化(Init)启动初始化是系统启动的第三阶段,它是用户空间的第一个进程(init进程)接管系统控制权后的操作。
启动初始化主要完成以下几个任务:1. 挂载根文件系统:启动初始化会挂载根文件系统,使得用户可以访问文件系统中的文件和目录。
2. 加载系统服务:启动初始化会加载并启动系统服务,比如网络服务、日志服务、时间同步服务等。
ARMLinux启动过程分析(1).
ARM Linux启动过程分析(1)摘要:嵌入式 Linux 的可移植性使得我们可以在各种电子产品上看到它的身影。
对于不同体系结构的处理器来说Linux的启动过程也有所不同。
本文以S3C2410 ARM处理器为例,详细分析了系统上电后 bootloader的执行流程及 ARM Linux的启动过程。
关键词:ARM Linux bootloader 启动过程Abstract:We can see embedded Linux in kinds of electronic productsb ecause of its portability. Linux’s start-up procedure for different processors is also different. This paper provides the analysis ofbootloader execution process and Linux kernel start-up procedure - taking the S3C2410 ARM processor as example. Keywords: ARM Linux bootloader start-up procedure 1. 引言 Linux 最初是由瑞典赫尔辛基大学的学生 Linus Torvalds在1991 年开发出来的,之后在 GNU的支持下,Linux 获得了巨大的发展。
虽然 Linux 在桌面 PC 机上的普及程度远不及微软的Windows 操作系统,但它的发展速度之快、用户数量的日益增多,也是微软所不能轻视的。
而近些年来 Linux 在嵌入式领域的迅猛发展,更是给 Linux 注入了新的活力。
一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(bootloader), Linux 内核,文件系统,应用程序。
其中bootloader是系统启动或复位以后执行的第一段代码,它主要用来初始化处理器及外设,然后调用 Linux 内核。
第二章--Bootloader启动流程分析
为运行域地址,通常为 RAM 的高端地址)测试内存空间是否有效; ③ 复制 Bootloader 的 stage2 代码到 RAM 空间中; ④ 设置好堆栈; ⑤ 跳转到 stage2 的 C 函数入口点。
/* 设置内存起始地址 */ params->u.mem.start = bd->bi_dram[i].start;
/* 设置内存大小 */ params->u.mem.size = bd->bi_dram[i].size; /* 使 params 指向下一个标记 */ params = tag_next (params); } }
标记的数据结构为 tag,它由一个 tag_header 结构体和一个联合体组成。
tag_header 结构体表示标记的长度和类型,比如是表示内存还是命令行参数。
对于不同类型的标记使用不同的联合体。对于 tag 和 tag_header 的定义可以在
网蜂提供的 U-Boot 的源码中 arch/arm/include/asm/setup.h 文件中找到,即:
/* 使 params 指向下一个标记 */ params = tag_next (params); }
static void setup_memory_tags (bd_t *bd) {
int i; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
/* 设置内存标记 */ params->hdr.tag = ATAG_MEM; params->hdr.size = tag_size (tag_mem32);
ARM的启动分析详解及应用
ARM的启动分析详解及应用ARM是一款广泛应用于嵌入式系统和移动设备的处理器架构。
在ARM的启动过程中,主要涉及到硬件初始化、加载引导程序和启动操作系统等步骤。
下面将对ARM的启动过程进行详细分析,并讨论其在实际应用中的应用。
硬件初始化:在ARM的启动过程中,首先需要对硬件进行初始化。
这包括对中央处理器(CPU)、存储器、外设等进行初始化操作。
例如,初始化CPU的控制和配置寄存器,设置存储器的访问模式和权限等。
硬件初始化的目的是确保系统处于一个稳定的状态,为后续的操作打下基础。
加载引导程序:引导程序是ARM启动的关键部分,它负责初始化系统环境和加载操作系统的镜像文件。
引导程序通常位于启动设备的引导扇区或者特定的存储器地址中。
在ARM中,引导程序可以是U-Boot、Das U-Boot或是其他自定义的引导程序。
加载引导程序的方式可以是通过串口、以太网或者其他类似的介质。
引导程序的主要功能是初始化设备和外设,配置内存和中断控制器等。
它会加载操作系统的镜像文件到内存中,并跳转到操作系统的起始地址,从而将控制权交给操作系统。
启动操作系统:在引导程序加载并跳转到操作系统的起始地址后,操作系统开始运行。
操作系统负责管理硬件资源、提供系统服务和支持应用程序的运行。
常见的ARM操作系统有Linux、Android等。
ARM的启动分析步骤在实际应用中具有重要的意义。
首先,通过硬件初始化可以确保系统处于一个稳定的状态,避免因为硬件问题导致系统崩溃或运行不正常。
其次,加载引导程序可以实现自定义的系统启动流程和初始化操作,满足特定应用需求。
最后,启动操作系统可以为用户提供高效、稳定的系统环境,并支持各种应用程序的运行。
在实际的应用中,ARM的启动分析步骤具有广泛的应用。
例如,嵌入式系统可以通过自定义的引导程序来实现特定的启动流程和初始化操作,以满足设备的需求。
移动设备则可以通过加载引导程序和启动操作系统来提供稳定的系统环境和良好的用户体验。
ARM体系架构下的linux启动之一,从bootloader到linux内核
ARM体系架构下的linux启动之一,从bootloader到linux内核1. bootloader 的启动bootloader 本身叫做嵌入式系统的引导程序。
但是,它支持X86,MIPS,PowerPC,ARM 等多种体系架构。
对于操作系统的启动来讲,当机器开始上电时,首先加载bootloader,它用来完成最基本的硬件的初始化,然后加载Linux 内核。
用于ARM 的bootloader 一般为U-BOOT,用它来完成对linux 内核的加载设置,一般bootloader 烧写在开发板的Flash 里,包括Nor Flash 或Nand Flash,其中由于NorFlash 支持芯片内执行XIP(eXcute In Place),代码可以直接在FLASH 上执行,而NandFlash 需要把代码拷到RAM 中再去执行。
但是RAM 的处理速度比Flash 的处理速度要快得多,一般仍然把代码放在RAM 中执行。
一般的bootloader 需要完成以下五种功能:1)RAM 的初始化:为调用linux 内核做准备。
2)串口的初始化:由于一般的嵌入式系统开发板上没有视频终端,只能用串口进行开发,串口的初始化非常重要。
3)检测处理器类型:用来预处理加载内核的处理器类型的传递工作。
4)设置Linux 的启动参数:包括加载地址,启动方式(从本地分区或NFS 进行根文件系统加载),以及Linux 根文件系统的加载方式。
通常用一个标记列表来记录linux 内核启动的各个参数。
5)调用linux 内核镜像:此时ARM 的处理器中的几个特殊的寄存器值:r0=0,r1=处理器类型,r2=标记列表在RAM 中的位置。
2. linux kernel 的启动分析。
基于ARM的嵌入式系统BootLoader的编译与启动分析
第 7卷 第 1 4期 2 0 年 7月 07 17 -8 9 20 )437 -4 6 11 1 ( 0 7 1-5 1 0
科
学
技
术
与
工
程
④
Vo. No 1 J l 0 7 17 .4 uy 2 0
S inc c noo y a d En i e rn ce eTe h lg n gn e i g
式 we 监 控 技 术 方 向 。E—n i: q _ u ig u 16 om。 b m l h w h qn w @ 2 . o
利用 数组 名 来 定 位 ss i bn文 件 , yi t i n. 因为 根 目录 下 的这个 ss i c还 要 被 编译 成 . 文 件 , 根 目录 yi t n. O 在
和异 常处 理程 序 , 始 化 存储 系统 , 初 配置 A M 各 种 R
Ia e — C i tc s a a lk l mg c l/p r m l a  ̄ 一 C i g o l.i g lk l r to s r a / a
模式 下 的数据栈 , 能异 常 中断 , 使 根据需 要切 换处 理 器模 式 和 状 态 等 等 。BoLae 否 成 功 地 运 行 , otodr能 取决 于该 嵌入 式系统 是 否能正 常 工作 。 本文 针对 B oLae 的编译 与启 动过 程 进行 了 otodr
能 模块 的可执 行 文 件 , 用 bn c将 子 文 件 夹 里 可 并 i 2 执 行 文件 生成 只包含 一 个 数 组 的 同名 C文 件 , 成 生 的 C文件 在根 目录下 。 以 ss i文件 为例 , yi t n
. .
/s sni. y ii. n y i t c s sn t bi
基于嵌入式ARM的Bootloader研究与实现
三、Bootloader的研究进展开嵌 入式ARM系统的Bootloader研究 与实现
三、Bootloader的研究进展开嵌入式ARM系统的Bootloader研究与 实现
嵌入式ARM系统在许多领域得到广泛应用,如工业控制、智能家居、通信设备 等。在这些应用场景中,Bootloader的作用不言而喻。本次演示将深入探讨嵌入 式ARM系统的Bootloader研究与实现。
内存管理模块主要负责内存的映射和保护工作。为了实现通用性,我们可以 采用内存分页和分段的技术来实现内存管理。通过将内存分为不同的段或页,我 们可以实现对内存的灵活管理。例如,我们可以将系统程序代码映射到 0x~0x0FFFFFFF的空间,将数据映射到0x~0x1FFFFFFF的空间等。
4、异常处理模块
一、Bootloader的启动过程
5、将引导程序加载到内存中,并跳转到该执行。
二、Bootloader的实现方法
二、Bootloader的实现方法
1、汇编语言实现:由于Bootloader需要直接与硬件打交道,因此通常使用 汇编语言实现。常用的汇编语言有ARM汇编和Keil汇编。
二、Bootloader的实现方法
基于嵌入式ARM的 Bootloader研究与实现
目录
01 一、Bootloader的 启动过程
03 三、Bootloader的 研究进展开嵌入式 ARM系统
02 二、Bootloader的 实现方法
04 参考内容
嵌入式ARM系统的Bootloader研 究与实现
嵌入式ARM系统的Bootloader研究与实现
三、通用Bootloader的实现
为了进一步实现通用的Bootloader,我们还需要使用一种可扩展的程序设计 方法。该方法允许我们在不更改程序代码的前提下,通过添加不同的模块来实现 不同的功能。例如,我们可以添加一个网络模块来实现从网络启动的功能;我们 也可以添加一个USB模块来实现从USB设备启动的功能。
armv8标准启动流程
ARMv8标准启动流程一、BL1阶段BL1(Bootloader 1)是ARMv8 架构中的第一个启动阶段。
当系统启动时,BL1 负责从非易失存储器中加载和执行接下来的引导加载程序(BL2 或BL31)。
在BL1 阶段,处理器会执行以下操作:初始化硬件:包括CPU、内存、中断控制器等。
加载BL2:通过BootROM(非易失存储器)加载BL2 到内存中。
设置异常向量表:为后续的异常处理提供支持。
进入C状态:处理器进入ARM C 模式,准备执行高级指令。
二、BL2阶段BL2(Bootloader 2)是ARMv8 架构中的第二个启动阶段。
在BL1 阶段完成后,BL2 会被加载到内存中并开始执行。
在BL2 阶段,处理器会执行以下操作:初始化硬件:包括网络接口、文件系统等。
加载并执行后续的引导加载程序(BL31 或BL33)。
设置异常向量表:为后续的异常处理提供支持。
进入C状态:处理器进入ARM C 模式,准备执行高级指令。
三、BL31/BL33阶段BL31 和BL33 是ARMv8 架构中的高级引导加载程序。
在BL2 阶段完成后,它们会被加载到内存中并开始执行。
在BL31 和BL33 阶段,处理器会执行以下操作:初始化硬件:包括GPU、I/O 设备等。
加载操作系统内核:将操作系统内核从非易失存储器中加载到内存中。
启动操作系统内核:通过引导加载程序调用操作系统内核的入口点,启动操作系统内核。
将控制权交给操作系统内核:将控制权交给操作系统内核,由操作系统内核负责后续的启动和运行过程。
总之,ARMv8 标准启动流程包括BL1、BL2、BL31 和BL33 四个阶段。
这些阶段依次执行,完成系统的初始化和启动过程,最终将控制权交给操作系统内核,由操作系统内核负责后续的运行和管理。
ARM11第9课bootloader代码分析
ARM裸板编程——bootloader代码分析简介bootloader从字面上理解就是“引导装载”的含义,它是在系统通电后就开始运行,它的任务主要是对硬件进行初始化,并以启动操作系统内核为终极目标的一段程序。
将操作系统内核启动完后,系统控制权就交予内核,bootloader的工作就结束了。
bootloader种类很多,我们之后学的u-boot,全称universal bootloader,即通用的bootloader,它遵循GPL条款的开放源代码项目。
这里的“通用”表示一、可以引导多种操作系统二、支持多种架构的CPU通用概念bootloader的实现是非常依赖于硬件的,如果硬件不同,bootloader的设置就不同。
有些CPU在运行bootloader前需要运行一段固化的程序(也称为固件)它的作用基本上是用来引导bootloader的,例如x86结构的CPU,就是先运行BIOS中的固件,然后才运行硬盘第一个分区中的bootloader。
在大多数嵌入式系统中并没有这些固件,bootloader是通电后执行的第一个程序。
bootloader的终极目标是启动操作系统内核的,bootloader将需要传给内核的参数固定放在一个地方,在内核启动之后由内核从那里取出这些参数进行使用。
LCD,基本上开发板相关的函数再次之前我们可以把源码包中和mini6410无关的文件删除以减少我们的阅读量,一般删除无关u-boot启动内核的过程因为u-boot的终极目标是启动内核,在启动内核之前u-boot会去对需要使用到的①硬件进行初始化,比如:时钟、串口、DDR、Flash等等。
内核一般我们都是通过USB线烧写到Nand Flash 中,u-boot还需要将内核②从Flash中复制③到DDR中,然后④传递参数并⑤启动内核。
为了方便使用还可以在u-boot中加入用户想要的功能,比如说:写Flash(u-boot、内核等)、USB相关功能、u-boot命令行等就将u-boot当做是一个比较复杂的裸板程序。
ARM-Linux嵌入式系统的BootLoader分析与设计.
ARM-Linux嵌入式系统的BootLoader分析与设计0引言由BootLoader和固化在固件(firmware)中的Boot代码(可选)共同组成一个嵌入式系统的引导加载程序。
它的作用和功能就像固化到计算机内主板上的一个ROM芯片程序BIOS(basicinputoutputsystem)。
但是它一般不配置像BIOS那样的固件程序,这是因为要考虑经济方面的原因,因此必须自己完成这方面的工作。
BootLoader可以初始化硬件设备,建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准0 引言由Boot Loader和固化在固件(firmware)中的Boot代码(可选)共同组成一个嵌入式系统的引导加载程序。
它的作用和功能就像固化到计算机内主板上的一个ROM芯片程序BIOS(basic input output system)。
但是它一般不配置像BIOS那样的固件程序,这是因为要考虑经济方面的原因,因此必须自己完成这方面的工作。
Boot Loader可以初始化硬件设备,建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
它的实现严重地依赖于硬件,特别是在嵌入式系统中,即使基于同一个CPU的Boot Loader,对于不同的板子,也有很大的不同。
1 Boot Loader分析系统加电,然后复位后,基本上所有的CPU都是从复位地址上取得指令的。
以微处理器为核心的嵌入式系统中,通常都有某种类型的固态存储设备(FLASH,E2PROM等),这个固态存储设备被映射到一个预先设置好的地址上。
在系统加电复位后,一开始处理器就会去执行存放在复位地址处的程序,而且通过开发环境可以将Boot Loader定位在复位地址一开始的存储空间上,因此Boot Loader是系统加电后,在操作系统内核或者一些应用程序被运行之前,首先会运行的程序。
Arm启动流程解析
Arm启动流程解析谈到arm 的启动流程不得不说的是bootloader,但是我这篇文章主要来谈谈arm 启动流程的,所以bootloader 只是跟大家简介一下就ok。
这篇文章我会谈到以下内容:1、bootloader 简介以及其作用2、2440、6410、210 当下比较常见的3 款处理器的启动流程进行简单分析,通过这三款处理器的分析希望大家掌握arm 处理器的启动分析。
Ok 我们进入主题lBootloader 简介及其作用在我看来bootloader 的作用是初始化必要的硬件,引导内核启动。
(当然这是主要作用,今天的重点不在bootloader,所以在我后面的博文会继续谈到的)l 启动流程分析在分析启动流程的时候我们将会使用的文档是三星公司提供的芯片手册,通过手册我们搞清楚芯片的启动。
在分析启动流程之前我们首先要清楚不论是arm 的何种处理器,其都是从0x0 0 地址处开始执行程序的。
下面的分析我将会通过三个方面:1、芯片支持的启动方式2、地址布局3、启动流程1.2440a)启动方式由上图可知,S3C2440 支持两种启动模式:NAND 和非NAND(这里是Nor Flash),具体采用的方式取决于OM0、OM1 两个引脚的状态。
b)地址布局我们知道arm 从0 地址出运行代码那么我们的零地址处到底存放的是什么东西呢?我们通过地址布局图来分析从上图我们可以清楚的看到左边的是从Nor Flash 启动的地址布局,右边是从NAND 启动的地址布局,因为Nor Flash 内可以运行程序,所以我们在放bootloader 的时候放在0 地址处即可,所以我们重点分析从NAND 启动。
c)启动流程我们从地址布局图中可以看到,当我们从NAND 启动的时候0 地址处是BootSRAM(又叫做stepping stone 垫脚石),当我们上电时其会做以下事情1.上电后处理器自动将nandflash 前4KB的内容到boot sram 开始执行(由硬件完成)。
ARM嵌入式系统Bootloader的设计与分析
经验交流44ARM嵌入式系统Bootloader的设计与分析李丽郝继飞杨莹陈章祥(中国矿业大学信息与电气工程学院)摘要:Bootloader的编写在嵌入式系统软件开发中非常重要。
基于S3C44B0X硬件平台,文章介绍了Bootloader开发的相关原理和设计方法。
对经过实践验证的启动代码,进行了详细的分析。
关键词:嵌入式系统;ARM;Bootloader;启动代码1引言嵌入式系统的Bootloader,类似于PC上的BIOS,是系统上电/复位后,内核启动程序之前执行的一段程序,用以完成整个系统的启动加载任务。
其功能主要是初始化CPU、内存控制器、看门狗等硬件设备,然后配置存储映射,建立系统的内存空间映射图(有的CPU没有内存映射功能如S3C44B0),从而将系统软硬件设置到合适状态,最后将操作系统内核解压加载到RAM中,并且跳转到操作系统的起始代码部分去执行。
它是嵌入式系统开发的一个难点,在整个开发中占有相当大分量。
由于依赖于实际的硬件和应用环境,要为嵌入式系统建立一个通用、标准的Bootloader是非常困难的。
开发者需要自行开发或移植Bootloader。
Bootloader 也依赖于具体的嵌入式板级设备的配置,也就是说,对于两块不同的嵌入式主板,即使它们是基于同一CPU而构建,要想让运行在一块板子上的Bootloader 程序也能运行在另一块板子上,通常都需要修改Bootloader的源程序。
本文以三星公司的S3C44BOX 为硬件平台,给出了Bootloader的设计和实现方案。
2系统平台简介本文嵌入式系统的硬件平台是基于三星的S3C44BOX微处理器。
S3C44BOX最突出的优点是它的CPU采用ARM公司的16/32位ARM7TDMI RISC 结构,工作在66MHz。
S3C44BOX通过在ARM7TDMI 内容的基础上扩展一系列完整的通用外围器件,使系统的费用降至最低,消除了增加附加配置的需要。
ARMlinux启动分析-Nathan.Yu的专栏-CSDN博客
ARMlinux启动分析-Nathan.Yu的专栏-CSDN博客linux启动分析(1)---bootloader启动内核过程我分析的是2.4.19的内核版本,是xscale的平台,参考了网上很多有价值的帖子,也加入了自己的一些看法,陆续总结成文字,今天是第一篇:内核一般是由bootloader来引导的,通过bootloader启动内核一般要传递三个参数,第一个参数放在寄存器0中,一般都为0,r0 = 0;第二个参数放在寄存器1中,是机器类型id,r1 = Machine Type Number;第三个参数放在寄存器2中,是启动参数标记列表在ram中的起始基地址;bootloader首先要将ramdisk(如果有)和内核拷贝到ram当中,然后可以通过c语言的模式启动内核:void (*startkernel)(int zero, int arch, unsigned int params_addr) = (void(*)(int, int, unsigned int))KERNEL_RAM_BASE;startkernel(0, ARCH_NUMBER, (unsigned int)kernel_params_start);其中KERNEL_RAM_BASE为内核在ram中启动的地址,ARCH_NUMBER是Machine Type Number,kernel_params_start 是参数在ram的偏移地址。
这时候就将全力交给了内核。
linux启动分析(2)---内核启动地址的确定内核编译链接过程是依靠vmlinux.lds文件,以arm为例vmlinux.lds文件位于kernel/arch/arm/vmlinux.lds,但是该文件是由vmlinux-armv.lds.in生成的,根据编译选项的不同源文件还可以是vmlinux-armo.lds.in,vmlinux-armv-xip.lds.in。
基于ARM的嵌入式系统Bootloader启动流程分析.
基于ARM的嵌入式系统Bootloader启动流程分析来源:西部工控网一. 引言:PC机,其开机后初始化处理器配置、硬件初始化等操作是由BIOS (Basic Input /Output System)完成,但嵌入式系统来说,出于经济性、价格方面考虑一般不配置BIOS,我们必须自行编写完成这些工作程序,这就是所需要开机程序。
而嵌入式系统中,通常并没有像 BIOS 那样固件程序,启动时用于完成初始化操作这段代码被称为Bootloader程序,整个系统加载启动任务就完全由Bootloader 来完成。
简单说,这段程序,可以初始化硬件设备、建立内存空间映射图(有CPU没有内存映射功能如S3C44B0),将系统软硬件环境设定一个合适状态,为最终调用操作系统内核、运行用户应用程序准备好正确环境。
Bootloader依赖于实际硬件和应用环境,要为嵌入式系统建立一个通用、标准Bootloader是非常困难。
Bootloader也依赖于具体嵌入式板级设备配置,这也就是说,两块不同嵌入式主板而言,它们是基于同一 CPU 而构建,要想让运行一块板子上 Bootloader 程序也能运行另一块板子上,通常都需要修改 Bootloader 源程序。
二. 启动流程系统加电复位后,几乎所有 CPU都从由复位址上取指令。
比如,基于 ARM7TDMI内核CPU复位时通常都从址 0x00000000处取它第一条指令。
而以微处理器为核心嵌入式系统通常都有某种类型固态存储设备(比如EEPROM、FLASH等)被映射到这个预先设置好址上。
系统加电复位后,处理器将首先执行存放复位址处程序。
集成开发环境可以将Bootloader定位复位址开始存储空间内,Bootloader是系统加电后、操作系统内核或用户应用程序运行之前,首先必须运行一段程序代码。
嵌入式系统来说,有使用操作系统,也有不使用操作系统,比如功能简单仅包括应用程序系统,但系统启动时都必须执行Bootloader,为系统运行准备好软硬件运行环境。
arm-linux启动流程分析
arm-linux启动流程分析arm-linux启动流程分析一.概述 (1)二.init进程 (1)三.inittab文件简要说明 (1)四.arm-linux系统的启动分析 (3)一.概述本文将讲述arm-linux内核启动后到进入用户shell模式这段时间的启动流程,从上电到进入kernel的过程请参见sourcesafe下“personal/yangxiyuan/资料”目录下的“ARM-linux启动流程.htm”文档。
二.init进程init进程是内核启动后的第一个用户级进程,是系统中所有进程的父进程,init进程的主要任务是按照inittab文件所提供的信息创建进程,init进程繁衍出完成通常操作所需的子进程,这些操作包括:设置机器名、检查和安装磁盘及文件系统、启动系统日志、配置网络接口并启动网络和邮件服务,启动打印服务等。
三.inittab文件简要说明inittab文件中每一记录都从新的一行开始,每个记录项最多可有512个字符,每一项的格式通常如下:id: run level:action:process,解释如下:id字段:是最多4个字符的字符串,用来唯一标志表项。
run level字段:定义该记录项被调用时的运行级别,run level可以由一个或多个运行级别构成,也可以是空,空则代表运行级别0~6。
# 0 - halt (Do NOT set initdefault to this)# - 关闭计算机,安全关闭电源# 1 - Single user mode# - 进入单用户维护模式,卸下除root以外的所有文件系统并杀死所有用户进程# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)# - 多用户模式,无网络连接# 3 - Full multiuser mode# - 多用户模式,并以文本方式作为登陆方式# 4 - unused# 5 - X11# - 多用户模式,并以图形方式作为登陆方式# 6 - reboot (Do NOT set initdefault to this)# - 停止linux系统,并按照/etc/inittab默认的登记项重新引导系统。
ARM启动代码分析
4.内部寄存器(31个通常32位寄存器和6个状态寄 存器)
5.状态寄存器
四、启动代码功能模块分析(也可参考<ARM Linux入门与实践>一书,边仿真跟踪边分 析)
• 启动CodeWarrior for ARM Developer Suite,选择File->Open…,在“打开”对话框的对 象类型项选择Project Files (*.mcp),在2410test目录下找到*.mcp文件将其打开,如右 图所示。
•
二、为什么要分析理解启动代码
•
初次接触ARM处理器的新手们此时可能会无从下手,而老手们肯定会 问"处理器到底运行了没有?",运行不运行,运行到哪里就要问启 动代码了.此时就需要去分析启动代码,如果有仿真器可以直接仿真 单步执行启动代码,没有仿真器则需要在启动代码中加LED测试灯等 来确认CPU是执行启动代码的哪一步出问题了
.
三、分析前应该知道的ARM体系结构与汇编 知识(参考<ARM Linux入门与实践> 一书)
• 1.ARM直接支持的数据类型:字节(8位)、半字(16位)和字 (32位)
பைடு நூலகம்
•
2.处理器状态:ARM(32位)和Thumb(16位)
3.处理器7种模式(异常)
• 用户(User) 快速中断模式(FIQ) 中断(IRQ) 管理(SVC) 中止(ABORT) 未定义(UNDEF) 系统(SWI)模式
图 5.2
2.看门狗及中断的禁止
• ResetHandler • ldr r0,=WTCON ;watch dog disable • ldr r1,=0x0 • str r1,[r0] • ldr r0,=INTMSK • ldr r1,=0xffffffff ;all interrupt disable • str r1,[r0] • ldr r0,=INTSUBMSK • ldr r1,=0x7ff ;all sub interrupt disable, 2002/04/10 • str r1,[r0]
ARM启动过程分析
ARM 启动过程的理解:第一篇参考文章1.在板子上电的一开始,首先自动判断是否是autoboot模式(这是由硬件设计阶段,由硬件工程师对mcu的引脚连线决定的),我所使用的s3c2410是带有nandflash的,并切被设置成autoboot,从nandflash开始启动.2.在判断是autoboot模式后,mcu内置的nandflash控制器自动将nandflash的最前面的4k区域(这4k区域存放着bootloader的最前面4k代码)拷贝到samsung所谓的"steppingstone"里面(实际上是一块4k大小的SRAM).这一过程完全由硬件自动实现,不需软件控制.3.在拷贝完前4k代码后,nandflash控制器自动将"steppingstone"映射到arm地址空间0x00000000开始的前4k区域.4.在映射过程完成后.nandflash控制器将pc指针直接指向arm地址空间的0x00000000位置,准备开始执行"steppingstone"上的代码.5.而"steppingstone"上从nandflash拷贝过来的4k代码,是程序员写的bootloader的前4k代码.这个bootloader在之前写好,并已经被烧写到nandflash的0x00000000开始的最前面区域..而这"steppingstone"上的4k代码就是bootloader的前4k代码.6.在pc指向arm地址空间的0x00000000后,系统就开始执行指令代码.这4k代码的任务是:初始化硬件,设置中断向量表,设置堆栈,然后一个很重要的任务是,将nandflash的最前面区域的bootloader(包含4k启动代码)拷贝到SDRAM中去,bootloader 代码的大小是写好bootloader就确定的.然后只需要确定bootloader想映射到SDRAM的起始位置就ok.7.在完成对nandflash上的bootloader搬移后,找到4k代码的搬移代码最后一个指令的下一个指令在SDRAM的bootloader 的地址,然后跳转到该位置,继续执行bootloader的剩余代码(引导系统).现在有这么几个问题:在启动启动完成后,steppingstone会被映射到其他地方,可以作为一般存储使用;为加快终端响应,需要将sdram开始的代码重新映射到0x00000000开始的一段区域,这样两个虚拟地址空间映射到一个物理内存区域;本文来自CSDN博客,转载请标明出处:/martree/archive/2008/11/17/3321639.aspx第二篇系统初始化流程如下:禁止看门狗——》在中断控制器中屏蔽所有中断——》系统时钟设置——》初始化端口——》DMA设置——》cashe和总线设置——》存储器设置,初始化SDRAM——》初始化堆栈——》设置IRQ和FIQ的入口——》地址重映射通常系统初始化有两个阶段组成,分别为汇编和C写成。
bootloader启动代码分析
bootloader启动代码分析1,bootloader(第一部分)主要完成以下工作:1,设置CPU工作模式;2,关闭中断;3,关闭Cache和Write buffer;4,初始化SDRAM,配置存储设备;5,复制FLASH中的代码和数据到SDRAM中;6,内存重映射,配置存储设备;7,把RM和ZI从LOAD ADDR 复制到execute ADDR.8,设置栈空间指针,跳转到C语言函数入口(启动代码第二部分)。
2,具体代码分析1,设置CPU工作模式MRS r0, cpsr#读取CPSR状态寄存器的值CPSR状态寄存器结构:BIC r0, r0, #MASK_MODE&定义值为0x0000003F,把MODE清零;ORR r0, r0, #MODE_SVC32&宏定义值为0x00000013,把MODE设置为SVC模式;ORR r0, r0, #I_BIT&宏定义值为0x80,关IRQ;ORR r0, r0, #F_BIT&宏定义值为0x40,关FIQ;MSR cpsr_c, r0&回写cpsr状态寄存器设置完CPSR后,状态寄存器中的值:2,关闭中断LDR r2, =ARM7_INTMASK& ARM7_INTMASK宏定义值为ASIC_BASE+0x4008,读取interrupt controller寄存器MVN r1, #0&FFFFFFFFSTR r1, [r2]&回写interrupt controller寄存器,之后寄存器的值为全1,既关闭所有的中断源;LDR r2, =ARM7_INTPEND&ARM7_INTPEND宏定义值为ASIC_BASE+0x4004,取interrupt pend 寄存器.MVN r1, #0 &FFFFFFFFSTR r1, [r2]&回写ARM7_INTPEND寄存器,之后寄存器的值为全1,既关闭所有的中断标志位;3,关闭Cache和Write bufferASIC_BASE宏定义值为0x03ff0000LDR r0, =ARM7_SYSCFG &宏定义值为ASIC_BASE+0x0000LDR r1, =0x87ffffA00X87ffffA0的二进制为 1000 0111 1111 1111 1111 1111 1010 0000 SE Must be set to zero.CE When set to '1', cache operations are enabled. 设置为0,将CACHE禁用。
ARM11bootloader启动流程分析汇编
ARM11 bootl oader 启动流程分析班级:通信1106学号:311109020623姓名:王贵林目录1 前言 (1)2 ARM 技术概述 (2)2.1 ARM以及处理器概述 (2)2.1.1 ARM 简介 (2)2.1.2 ARM11处理器简介 (2)2.2 ARM微处理器体系结构 (3)2.2.1 ARM处理器寄存器组 (3)2.2.2 ARM处理器指令集 (4)2.2.3 ARM处理器寻址方式 (5)2.2.4 ARM11处理器工作模式 (6)3 开发工具 (7)3.1 软件工具 (7)3.1.1虚拟机 (7)3.1.2 redhat linux6 (7)3.1.3交叉工具链 (7)3.1.4 eclipse调试工具 (7)3.1.5链接器脚本 (7)3.1.6 Makefile工程管理器 (7)3.2硬件工具 (7)3.2.1 S3C6410开发板 (7)3.2.2 Jlink模拟下载器 (8)4 Bootloader 在s3c6410平台实现 (9)4.1初始化流程 (9)4.2初始化过程概述 (9)4.2.1 6410启动方式 (9)4.2.2 6410启动过程概述 (10)4.2.3 iROM启动过程简介 (11)4.3 BL1初始化阶段分析 (12)4.3.1创建异常向量表及代码实现 (12)4.3.2设置svc及代码实现 (14)4.3.3关闭看门狗及代码实现 (14)4.3.4关闭中断及代码实现 (16)4.3.5关闭Cache和mmu及代码实现 (17)4.3.6时钟终初始化及代码实现 (19)4.3.7内存初始化及代码实现 (27)4.3.8代码搬移及代码实现 (42)4.3.9 C语言环境初始化及代码实现 (43)结论 (45)致谢 (46)参考文献 (47)附录 (48)1 前言随着中国市场经济的持续发展和人民生活水平的不断提高。
智能家居,智能穿戴,物联网等一系列嵌入式产品逐渐进入家家户户。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Boot Loader 的主要任务与典型结构框架在继续本节的讨论之前,首先我们做一个假定,那就是:假定内核映像与根文件系统映像都被加载到RAM 中运行。
之所以提出这样一个假设前提是因为,在嵌入式系统中内核映像与根文件系统映像也可以直接在ROM 或Flas h 这样的固态存储设备中直接运行。
但这种做法无疑是以运行速度的牺牲为代价的。
从操作系统的角度看,Boot Loader 的总目标就是正确地调用内核来执行。
另外,由于Boot Loader 的实现依赖于CPU 的体系结构,因此大多数Boo t Loader 都分为stage1 和stage2 两大部分。
依赖于CPU 体系结构的代码,比如设备初始化代码等,通常都放在stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。
而stage2 则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。
Boot Loader 的stage1 通常包括以下步骤(以执行的先后顺序):·硬件设备初始化。
·为加载Boot Loader 的stage2 准备RAM 空间。
·拷贝Boot Loader 的stage2 到RAM 空间中。
·设置好堆栈。
·跳转到stage2 的C 入口点。
Boot Loader 的stage2 通常包括以下步骤(以执行的先后顺序):·初始化本阶段要使用到的硬件设备。
·检测系统内存映射(memory map)。
·将kernel 映像和根文件系统映像从flash 上读到RAM 空间中。
·为内核设置启动参数。
·调用内核。
3.1 Boot Loader 的stage13.1.1 基本的硬件初始化这是Boot Loader 一开始就执行的操作,其目的是为stage2 的执行以及随后的kernel 的执行准备好一些基本的硬件环境。
它通常包括以下步骤(以执行的先后顺序):1.屏蔽所有的中断。
为中断提供服务通常是OS 设备驱动程序的责任,因此在Boot Loader 的执行全过程中可以不必响应任何中断。
中断屏蔽可以通过写CPU 的中断屏蔽寄存器或状态寄存器(比如ARM 的CPSR 寄存器)来完成。
2.设置CPU 的速度和时钟频率。
3.RAM 初始化。
包括正确地设置系统的内存控制器的功能寄存器以及各内存库控制寄存器等。
4.初始化LED。
典型地,通过GPIO 来驱动LED,其目的是表明系统的状态是OK 还是Error。
如果板子上没有LED,那么也可以通过初始化UART 向串口打印Boot Loader 的Logo 字符信息来完成这一点。
5.关闭CPU 内部指令/数据cache。
3.1.2 为加载stage2 准备RAM 空间为了获得更快的执行速度,通常把stage2 加载到RAM 空间中来执行,因此必须为加载Boot Loader 的stage2 准备好一段可用的RAM 空间范围。
由于stage2 通常是 C 语言执行代码,因此在考虑空间大小时,除了stage 2 可执行映象的大小外,还必须把堆栈空间也考虑进来。
此外,空间大小最好是memory page 大小(通常是4KB)的倍数。
一般而言,1M 的RAM 空间已经足够了。
具体的地址范围可以任意安排,比如blob 就将它的stage2 可执行映像安排到从系统RAM 起始地址0xc0200000 开始的1M 空间内执行。
但是,将stage2 安排到整个RAM 空间的最顶1MB(也即(RamEnd-1 MB) - RamEnd)是一种值得推荐的方法。
为了后面的叙述方便,这里把所安排的RAM 空间范围的大小记为:stage2_s ize(字节),把起始地址和终止地址分别记为:stage2_start 和stage2_end (这两个地址均以4 字节边界对齐)。
因此:stage2_end=stage2_start+stage2_size另外,还必须确保所安排的地址范围的的确确是可读写的RAM 空间,因此,必须对你所安排的地址范围进行测试。
具体的测试方法可以采用类似于blob的方法,也即:以memory page 为被测试单位,测试每个memory page 开始的两个字是否是可读写的。
为了后面叙述的方便,我们记这个检测算法为:test_mempage,其具体步骤如下:1.先保存memory page 一开始两个字的内容。
2.向这两个字中写入任意的数字。
比如:向第一个字写入0x55,第2 个字写入0xaa。
3.然后,立即将这两个字的内容读回。
显然,我们读到的内容应该分别是0x 55 和0xaa。
如果不是,则说明这个memory page 所占据的地址范围不是一段有效的RAM 空间。
4.再向这两个字中写入任意的数字。
比如:向第一个字写入0xaa,第2 个字中写入0x55。
5.然后,立即将这两个字的内容立即读回。
显然,我们读到的内容应该分别是0xaa 和0x55。
如果不是,则说明这个memory page 所占据的地址范围不是一段有效的RAM 空间。
6.恢复这两个字的原始内容。
测试完毕。
为了得到一段干净的RAM 空间范围,我们也可以将所安排的RAM 空间范围进行清零操作。
3.1.3 拷贝stage2 到RAM 中拷贝时要确定两点:(1) stage2 的可执行映象在固态存储设备的存放起始地址和终止地址;(2) RAM 空间的起始地址。
3.1.4 设置堆栈指针sp堆栈指针的设置是为了执行 C 语言代码作好准备。
通常我们可以把sp 的值设置为(stage2_end-4),也即在 3.1.2 节所安排的那个1MB 的RAM 空间的最顶端(堆栈向下生长)。
此外,在设置堆栈指针sp 之前,也可以关闭led 灯,以提示用户我们准备跳转到stage2。
经过上述这些执行步骤后,系统的物理内存布局应该如下图2所示。
3.1.5 跳转到stage2 的C 入口点在上述一切都就绪后,就可以跳转到Boot Loader 的stage2 去执行了。
比如,在ARM 系统中,这可以通过修改PC 寄存器为合适的地址来实现。
图2 bootloader 的stage2 可执行映象刚被拷贝到RAM 空间时的系统内3.2 Boot Loader 的stage2正如前面所说,stage2 的代码通常用 C 语言来实现,以便于实现更复杂的功能和取得更好的代码可读性和可移植性。
但是与普通 C 语言应用程序不同的是,在编译和链接boot loader 这样的程序时,我们不能使用glibc 库中的任何支持函数。
其原因是显而易见的。
这就给我们带来一个问题,那就是从那里跳转进main() 函数呢?直接把main() 函数的起始地址作为整个stage2 执行映像的入口点或许是最直接的想法。
但是这样做有两个缺点:1)无法通过main() 函数传递函数参数;2)无法处理main() 函数返回的情况。
一种更为巧妙的方法是利用trampoline(弹簧床)的概念。
也即,用汇编语言写一段tra mpoline 小程序,并将这段trampoline 小程序来作为stage2 可执行映象的执行入口点。
然后我们可以在trampoline 汇编小程序中用CPU 跳转指令跳入main() 函数中去执行;而当main() 函数返回时,CPU 执行路径显然再次回到我们的trampoline 程序。
简而言之,这种方法的思想就是:用这段trampoline 小程序来作为main() 函数的外部包裹(external wrapper)。
下面给出一个简单的trampoline 程序示例(来自blob):.text .globl _trampoline _trampoline: bl main /* if main ever retu rns we just call it again */ b _trampoline可以看出,当main() 函数返回后,我们又用一条跳转指令重新执行trampol ine 程序――当然也就重新执行main() 函数,这也就是trampoline(弹簧床)一词的意思所在。
3.2.1初始化本阶段要使用到的硬件设备这通常包括:(1)初始化至少一个串口,以便和终端用户进行I/O 输出信息;(2)初始化计时器等。
在初始化这些设备之前,也可以重新把LED 灯点亮,以表明我们已经进入main() 函数执行。
设备初始化完成后,可以输出一些打印信息,程序名字字符串、版本号等。
3.2.2 检测系统的内存映射(memory map)所谓内存映射就是指在整个4GB 物理地址空间中有哪些地址范围被分配用来寻址系统的RAM 单元。
比如,在SA-1100 CPU 中,从0xC000,0000开始的512M 地址空间被用作系统的RAM 地址空间,而在Samsung S3C 44B0X CPU 中,从0x0c00,0000 到0x1000,0000 之间的64M 地址空间被用作系统的RAM 地址空间。
虽然CPU 通常预留出一大段足够的地址空间给系统RAM,但是在搭建具体的嵌入式系统时却不一定会实现CPU 预留的全部RAM 地址空间。
也就是说,具体的嵌入式系统往往只把CPU 预留的全部RAM 地址空间中的一部分映射到RAM 单元上,而让剩下的那部分预留R AM 地址空间处于未使用状态。
由于上述这个事实,因此Boot Loader 的st age2 必须在它想干点什么(比如,将存储在flash 上的内核映像读到RAM 空间中) 之前检测整个系统的内存映射情况,也即它必须知道CPU 预留的全部RAM 地址空间中的哪些被真正映射到RAM 地址单元,哪些是处于'unused ' 状态的。
(1) 内存映射的描述可以用如下数据结构来描述RAM 地址空间中的一段连续(continuous)的地址typedef struct memory_area_struct {u32 start; /* the base address of the memory region */u32 size; /* the byte number of the memory region */int used;} memory_area_t;这段RAM 地址空间中的连续地址范围可以处于两种状态之一:(1)used=1,则说明这段连续的地址范围已被实现,也即真正地被映射到RAM 单元上。
(2) used=0,则说明这段连续的地址范围并未被系统所实现,而是处于未使用状态。
基于上述memory_area_t 数据结构,整个CPU 预留的RAM 地址空间可以用一个memory_area_t 类型的数组来表示,如下所示:memory_area_t memory_map[NUM_MEM_AREAS] = {[0 ... (NUM_MEM_AREAS - 1)] = {.start = 0,.size = 0,.used = 0},};[此贴子已经被作者于2006-8-17 10:45:03编辑过](2) 内存映射的检测下面我们给出一个可用来检测整个RAM 地址空间内存映射情况的简单而有效的算法:/* 数组初始化*/for(i = 0; i < NUM_MEM_AREAS; i++)memory_ed = 0;/* first write a 0 to all memory locations */for(addr = MEM_START; addr < MEM_END; addr += PAGE_SIZE) * (u32 *)addr = 0;for(i = 0, addr = MEM_START; addr < MEM_END; addr += PAGE _SIZE) {/** 检测从基地址MEM_START+i*PAGE_SIZE 开始,大小为* PAGE_SIZE 的地址空间是否是有效的RAM地址空间。