Linux-arm底层启动流程简介

合集下载

ARM的启动过程详解

ARM的启动过程详解

基于arm的芯片多数为复杂的片上系统,这种复杂系统里的多数硬件模块都是可配置的,需要由软件来设置其需要的工作状态。

因此在用户的应用程序之前,需要由专门的一段代码来完成对系统的初始化。

由于这类代码直接面对处理器内核和硬件控制器进行编程,一般都是用汇编语言。

一般通用的内容包括:中断向量表初始化存储器系统初始化堆栈初始化有特殊要求的断口,设备初始化用户程序执行环境改变处理器模式呼叫主应用程序中断向量表arm要求中断向量表必须放置在从0地址开始,连续8X4字节的空间内。

每当一个中断发生以后,arm处理器便强制把PC指针置为向量表中对应中断类型的地址值。

因为每个中断只占据向量表中1个字的存储空间,只能放置一条arm指令,使程序跳转到存储器的其他地方,再执行中断处理。

中断向量表的程序实现通常如下表示:AREA Boot,CODE,READONLYENTRYB ResetHandlerB UndefHandlerB SWIHandlerB PreAbortHandlerB DataAbortHandlerBB IRQHandlerB FIQHandler其中关键字ENTRY是指定编译器保留这段代码,因为编译器可能会认为这是一段亢余代码而加以优化。

链接的时候要确保这段代码被链接在0地址处,并且作为整个程序的入口。

初始化存储器系统存储器类型和时序配置通常Flash和SRAM同属于静态存储器类型,可以合用同一个存储器端口;而DRAM因为有动态刷新和地址线复用等特性,通常配有专用的存储器端口。

存储器端口的接口时序优化是非常重要的,这会影响到整个系统的性能。

因为一般系统运行的速度瓶颈都存在于存储器访问,所以存储器访问时序应尽可能的快;而同时又要考虑到由此带来的稳定性问题。

存储器地址分布一种典型的情况是启动ROM的地址重映射。

初始化堆栈因为arm有7种执行状态,每一种状态的堆栈指针寄存器(SP)都是独立的。

因此,对程序中需要用到的每一种模式都要给SP定义一个堆栈地址。

arm的启动过程

arm的启动过程

arm的启动过程ARM是一种广泛应用于嵌入式系统和移动设备的处理器架构。

在学习ARM的过程中,了解其启动过程是非常重要的。

本文将详细介绍ARM的启动过程。

ARM的启动过程可以分为四个主要阶段:复位阶段、启动阶段、初始化阶段和操作系统启动阶段。

在复位阶段,当ARM处理器上电或者接收到复位信号时,它会进入复位状态。

在这个阶段,处理器会初始化一些重要的寄存器,例如程序计数器(PC)和堆栈指针(SP)。

此外,处理器还会加载一些固定位置的向量表,这些向量表包含了处理器在不同中断或异常发生时所需要执行的代码。

接下来是启动阶段,处理器会根据向量表中指定的地址跳转到相应的启动代码。

启动代码的任务是设置处理器的工作模式和时钟频率。

在这个阶段,处理器会切换到特权模式,例如特权模式(SVC),以便能够访问特权指令和寄存器。

同时,处理器还会根据外部存储器中的配置信息来设置时钟频率,以确保处理器能够正常工作。

进入初始化阶段后,处理器会执行一系列初始化代码,包括初始化外部存储器、初始化外设和设置中断控制器等。

在这个阶段,处理器会根据配置信息初始化外部存储器,例如SDRAM或Flash存储器。

同时,处理器还会初始化外设,例如串口、GPIO和定时器等,以便与外部设备进行通信。

此外,处理器还会设置中断控制器,以便处理外部中断信号。

最后是操作系统启动阶段,在这个阶段,处理器会加载操作系统的启动代码,并跳转到操作系统的入口地址。

操作系统的启动代码会进一步初始化系统资源,例如内存管理单元(MMU)、进程管理和设备驱动等。

一旦操作系统初始化完成,处理器就可以开始执行操作系统的任务调度和应用程序的执行。

总结起来,ARM的启动过程包括复位阶段、启动阶段、初始化阶段和操作系统启动阶段。

在这个过程中,处理器会进行一系列的初始化操作,包括设置寄存器、加载向量表、设置工作模式和时钟频率、初始化外部存储器和外设、设置中断控制器以及加载操作系统的启动代码。

Arm_linux_启动分析

Arm_linux_启动分析

Arm linux 启动分析(1)王利明 walimi@ 宋振宇zhenyusong@ 2003-3-201.概述:在内核运行之前需要系统引导程序(Bootloader)完成加载内核和一些辅助性的工作,然后跳转到内核代码的起始地址并执行。

本文先分析了Bootloader 的初始化工作,接着从内核镜像的起始地址进行分析。

整个arm linux 内核的启动可分为三个阶段:第一阶段主要是进行cpu 和体系结构的检查、cpu 本身的初始化以及页表的建立等;第二阶段主要是对系统中的一些基础设施进行初始化;最后则是更高层次的初始化,如根设备和外部设备的初始化。

第一阶段的初始化是从内核入口(ENTRY(stext))开始到start_kernel 前结束。

这一阶段的代码在/arch/arm/head_armv.S 中。

2.Bootloader 2.1简介 本处介绍主要来自内核源代码下的Documentation/arm/Booting 文件,适合于arm linux 2.4.18-rmk6及以上版本。

Bootloader 主要作用是初始化一些必要的设备,然后调用内核,同时传递参数给内核。

主要完成如下工作:1. 建立和初始化RAM 。

2. 初始化一个串口。

3.4.建立内核的5. 调用内核镜像。

2.2功能详细介绍 1.建立和初始化RAM 。

要求:必须功能:探测所有的RAM 位置和大小,并对RAM 进行初始化。

2.初始化一个串口。

要求:可选,建议功能:Bootloader 应该初始化并启动一个串口。

这可以让内核的串口驱动自动探测哪个串口作为内核的控制台。

另外也可以通过给内核传递“console=”参数完成此工作。

3.检测机器的系统结构。

要求:必须功能:Bootloader 应该通过某种方法探测机器类型,最后传递给内核一个MACH_TYPE_xxx 值,这些值参看4要求:必须功能:Bootloader 必须创建和初始化内核的tagged list 。

Linuxarm底层启动流程简介

Linuxarm底层启动流程简介

Linux开发驱动底层环境启动流程Uboot编译:rm -rf 删除命令tar xjf 解压uboot文件patch -p1 < ../u-boot-1.1.6.jz2440.patch 打补丁 -p1 指示忽略第一个斜杠前因为已经在当前目录。

打好补丁之后配置文件make 100ask24x0_config之后make配置文件是厂家提供好的。

Make后生成bin文件,在Windows下进入oflash目录烧写这个文件。

选择Open jtag S2C2440 nand flash 0块0 2 0 0 0这几个数字烧写之后进入启动界面之后uboot命令按help查看支持哪些命令。

?Md 查看 md命令Print 命令查看环境变量设置环境变量 set xxxx xx savereset重启Uboot 的终极目的就是要启动内核。

Make config 就相当于执行命令100ask24x0_config : unconfig@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0NULL s3c24x0MKCONFIG := $(SRCTREE)/mkconfig$(@:_config=) $(@ 表示目标文件100ask24x0 _config=) 表示替换掉他用后面的arm arm920t 100ask24x0 NULL s3c24x0 100ask24x0最后就执行这个命令Mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0找到脚本文件mkconfig #!/bin/sh表示他是用bin目录下sh解释执行,后面是传入的参数。

这个配置过程它做了一些连接工作,把arm board arch 链接到现在的文件。

编译时的make 做的工作:用到了上面配置的config.mk(.a文件表示所有编译好的文件打包成成的一个库)OBJS = cpu/arm920/xxxxLib +=xxxx.aALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)依赖$(obj)u-boot.bin文件$(obj)u-boot.bin他又依赖于$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \-Map u-boot.map -o u-boot得到的bin文件就是这个.a文件如何组织连接在lds连接文件有说明链接地址在0x33f80000就是说应该在这个地址运行比如从0x00000000 到0x08000000是128M空间2^27次方=2^7*2^10*2^10=128M搜索命令 grep “” - nR内存一共64M0x33f80000空出512KUBOOT做一些工作:进入管理模式、关看门狗中断、初始化存储控制器、设置栈IRQFIQ、重定位(NORflash不能像内存一样写)、从flash拷到sdram、到他该运行的地址0x33f80000、清BSS段、调用C函数从上往下依次是512K UBOOT 然后是用来实现malloc接下来是全局参数,在接下来就是各种模式的栈。

arm版本linux系统的启动流程

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).

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 内核。

ARM体系架构下的linux启动之一,从bootloader到linux内核

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-Linux内核移植之(一)——内核启动流程分析

ARM-Linux内核移植之(一)——内核启动流程分析

ARM-Linux内核移植之(一)——内核启动流程分析Y-Kee转载请注明来自于衡阳师范学院08电2 Y-Kee /ayangke, QQ:843308498内核版本:2.6.22 为什么要采用这样一个较低的版本进行移植了,因为韦东山大牛说了,低版本的才能学到东西,越是高版本需要移植时做的工作量越少,学的东西越少。

内核启动分为三个阶段,第一是运行head.S文件和head-common.S,第三个阶段是允许第二是运行main.c文件对于ARM的处理器,内核第一个启动的文件是arc/arm/kernel下面的head.S文件。

当然arc/arm/boot/compress下面也有这个文件,这个文件和上面的文件略有不同,当要生成压缩的内核时zImage时,启动的是后者,后者与前者不同的时,它前面的代码是做自解压的,后面的代码都相同。

我们这里这分析arc/arm/kernel下面的head.S文件。

当head.S所作的工作完成后它会跳到init/目录下跌的main.c的start_kernel函数开始执行。

第一阶段:首先截取部分head.S文件,将后面重点要分析的代码高亮显示。

ENTRY(stext)msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode@ and irqs disabledmrc p15, 0, r9, c0, c0 @ get processor idbl __lookup_processor_type @ r5=procinfo r9=cpuidmovs r10, r5 @ invalid processor (r5=0)?beq __error_p @ yes, error 'p'bl __lookup_machine_type @ r5=machinfomovs r8, r5 @ invalid machine (r5=0)?beq __error_a @ yes, error 'a'bl __create_page_tables/** The following calls CPU specific code in a position independent* manner. See arch/arm/mm/proc-*.S for details. r10 = base of* xxx_proc_info structure selected by __lookup_machine_type* above. On return, the CPU will be ready for the MMU to be* turned on, and r0 will hold the CPU control register value.*/ldr r13, __switch_data @ address to jump to after@ mmu has been enabledadr lr, __enable_mmu @ return (PIC) address第一步,执行的是__lookup_processor_type,这个函数是检查处理器型号,它读取你的电路板的CPU型号与内核支持的处理器进行比较看是否能够处理。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux开发驱动底层环境启动流程Uboot编译:rm -rf 删除命令
tar xjf 解压uboot文件
patch -p1 < ../u-boot-1.1.6.jz2440.patch 打补丁 -p1 指示忽略第一个斜杠前因为已经在当前目录。

打好补丁之后配置文件make 100ask24x0_config之后make
配置文件是厂家提供好的。

Make后生成bin文件,在Windows下进入oflash目录烧写这个文件。

选择Open jtag S2C2440 nand flash 0块
0 2 0 0 0这几个数字
烧写之后进入启动界面之后uboot命令按help查看支持哪些命令。

?Md 查看 md命令
Print 命令查看环境变量
设置环境变量 set xxxx xx save
reset重启
Uboot 的终极目的就是要启动内核。

Make config 就相当于执行命令
100ask24x0_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0
NULL s3c24x0
MKCONFIG := $(SRCTREE)/mkconfig
$(@:_config=) $(@ 表示目标文件100ask24x0 _config=) 表示
替换掉他用后面的arm arm920t 100ask24x0 NULL s3c24x0 100ask24x0
最后就执行这个命令
Mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0
找到脚本文件mkconfig #!/bin/sh表示他是用bin目录下sh解释执行,后面是传入的参数。

这个配置过程它做了一些连接工作,把arm board arch 链接到现在的文件。

编译时的make 做的工作:用到了上面配置的config.mk
(.a文件表示所有编译好的文件打包成成的一个库)
OBJS = cpu/arm920/xxxx
Lib +=xxxx.a
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
依赖$(obj)u-boot.bin文件
$(obj)u-boot.bin他又依赖于
$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
得到的bin文件就是这个
.a文件如何组织连接在lds连接文件有说明
链接地址在0x33f80000就是说应该在这个地址运行
比如从0x00000000 到0x08000000是128M空间
2^27次方=2^7*2^10*2^10=128M
搜索命令 grep “” - nR
内存一共64M0x33f80000空出512K
UBOOT做一些工作:进入管理模式、关看门狗中断、初始化存储控制器、设置栈IRQFIQ、重定位(NORflash不能像内存一样写)、从flash拷到sdram、到他该运行的地址0x33f80000、清BSS段、调用C函数
从上往下依次是512K UBOOT 然后是用来实现malloc接下来是全局参数,在接下来就是各种模式的栈。

接下来刚才调用的C函数在这里执行完成大部分初始化包括以下初始化。

在BOARD_INIT中定义了机器ID(有一个gd结构体在那个全局参数中),内核启动身后参数存放的位置。

0x30000100处内核存放在0x30008000期间还有页表。

最后进入main_loop()函数这个函数看是否设置了读秒的环境参数没有的话直接等待,如果设置了读秒的环节就会等待输入如果
没有输入的话就会直接执行bootcmd环境变量进而启动内核,有的话等待串口输入。

Bootcmd这个环境变量里是从nand读到0x30007fc0去读从kernel分区去读。

然后bootm 0x30007fc0就启动了内核。

环境变量是用run_commad去执行的他是怎么执行的?根据结构体每个命令都会有一个结构体比如bootcmd、{
.name
.fun()
}然后调用fun()就执行了命令
对于bootcmd中nand命令表示从nand中读,bootm表示从内存中读。

The_kernel()函数一旦运行,控制权就交给了系统。

Linux系统
Find -name “defconfig”
编译:patch -p1 < ../补丁文件
配置:一、make menuconfig
二、使用默认的配置在此基础上修改
三、使用厂家的配置文件
直接把厂家提供的config复制为.config因为menuconfig会根据.config出现相关配置选项最后会在auto.conf中说明出哪些被编译进内核哪些被编译成为模块同时生成autoconfig.h文件里面有#define CONFIG_DEBUG_NX_TEST_MODULE 1
我们在使用make menuconfig时,首先会确定架构arch,然后读取arch目录的Kconfig 中的配置宏定义,生成编译条目,然后读取Linux内核根目录下的.config选项,将.config 中的配置信息显示在图形界面上[*] [M] or []。

我们在图形界面中更改配置选项会自动保存到.config文件中。

编译过程根据.config随后生成auto.conf文件,它决定了makefile 中各个文件的编译类型,静态编译进内核、编译成模块、不编译;同时生成autoconf.h,它以C语言宏定义的形式表达了各个文件是否被编译,源码中会判断某文件是否被编译进行不同的处理。

Makefile:uiamge依赖Vmlinux
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
首先执行head.s文件
处理传进来的参数,判断是否支持这个单板
怎么判断?
利用一个宏把一个结构体里面有机器ID和传入变量位置等等强制转换为段放进lds连接文件。

然后一一比较。

然后建立页表
启动MMU
执行start_kernel完成各种初始化,处理传进来的参数之后调用rest_init->kernel_init->prepar_namespace->mount_root挂接好的话调用init_post执行应用程序。

相关文档
最新文档