Uboot学习笔记②---(bootloader的一些共同特性、uboot启动过程、编译环境、地址规划设计)
2014-11-18 15:50
627 查看
本文所有资料来至互联网,笔者加以整理和归纳,仅供以后复习
一、bootloader一些共性
一个嵌入式Linux系统从软件的角度看通常可以分为四个层次:引导加载程序、Linux内核、文件系统、用户应用程序。嵌入式Linux系统中常用的bootloader有armboot、redboot、blob、u-boot等,u-boot是Sourceforge网站上的一个开放源代码的项目。它可对 PowerPCMPC5xx、MPC8xx、MPC82xx、MPC7xx、MPC74xx、ARM(ARM7、ARM9、strongARM、XScaLe)、MIPS(4kc、5kc)、X86等处理器提供支持,支持的嵌入式操作系统有Linux、Vx-WorkS、NetBSD、QNX、RTEMS、ARTOS、LynxOS等,
对于ARM bootloader的一些共同特性,理论上只局限于bootloader的基本功能,因为扩展功能众多,可以有串口、USB、以太网接口、IDE、CF等,无法进行归纳与总结。
对于一个ARM系统来说,本质上,bootloader作为引导与加载内核镜像的“工具”,在实现上,必须提供以下几个功能,更确切地说,必须做到以下几点:
(1)初始化RAM(必需):bootloader必须能够初始化RAM,因为将来系统要通过它保存一些Volatile数据,但具体地实现要依赖与具体的CPU以及硬件系统。
(2)初始化串口(可选,推荐):bootloader应该要初始化以及使能至少一个串口,通过它与控制台联系进行一些debug的工作;甚至与PC通信。
(3)创建内核参数列表(针对linux操作系统,推荐)。
(4)启动内核镜像(必需):根据内核镜像保存的存储介质不同,可以有两种启动方式:FALSH启动以及RAM启动;但是无论是哪种启动方式,下面的系统状态必须得到满足:
a、 CPU寄存器的设置: R0=0;
R1=机器类型;
R2=启动参数标记列表在RAM中的起始地址;
这三个寄存器的设置是在最后启动内核时通过启动参数来传递完成的。
直接跳转至RAM中的内核镜像的第一条指令执行:
linux_kernel = (void (*)(int, int, struct tag*))ram_start;
linux_kernel(LINUX_ARG0, LINUX_ARG1,tagparams);
其中,三个参数的函数如下:
LINUX_ARG0固定为0;
LINUX_ARG1为表征系统机器类型,要与内核中的一致;
Tagparams为系统传给内核的参数列表的首物理地址。
以汇编角度看,最终这三个参数会对应系统寄存器R0,R1和R2。
启动参数详细说明:
设置启动参数,现今的Linux内核都以链表(taggedlist)的形式来传递参数,启动参数以标记ATAG_CORE开始,ATAG_NONE结束。任何bootloader想要传递给kernel的参数都可以添加在在这两个表头与表尾之间。相关的代码如下:
struct tag* params = (struct tag *)BOOT_PARAMS; params->hdr.size= tag_size(tag_core); params->hdr.tag= ATAG_CORE; params->u.core.flags= 0; params->u.core.pagesize= 0; params->u.core.rootdev= 0; params= tag_next(params); //如果有参数传递,在此添加 params->hdr.size = 0; params->hdr.tag= ATAG_NONE; //其中,相关数据结构如下: struct tag_header { ulongsize; ulongtag; }; struct tag { struct tag_header hdr; union{ structtag_core core; structtag_mem32 mem; structtag_videotext videotext; structtag_ramdisk ramdisk; structtag_initrd initrd; structtag_serialnr serialnr; structtag_revision revision; structtag_videolfb videolfb; structtag_cmdline cmdline; struct tag_acorn acorn; structtag_memclk memclk; }u; };
b、 CPU模式: 关闭中断;
属于SVC模式;
Bootloader中没有必要支持中断的实现,这属于内核机制以及设备驱动管理的管理范畴;SVC模式是系统的一种保护模式,这样就可以进行一些只能在SVC模式下的操作,例如一些特定寄存器访问操作。
c、 Cache和MMU的设置: MMU必须关闭;
数据cache必须关闭;
指令cache可以关闭也可以开启;
Bootloader中所有对地址的操作都是使用物理地址,是实在的实地址,不存在虚拟地址,因此MMU必须关闭。Bootloader主要是装载内核镜像,镜像数据必须真实写回SDRAM中,所以数据cache必须关闭;而对于指令cache,不存在强制性的规定,但是一般情况下,推荐关闭指令cache。
d、 Bootloader启动内核镜像的方法:是通过跳转语句直接跳转至内核镜像的第一句指令语句。
二、uboot启动过程
Uboot启动分为两个阶段:阶段一主要为汇编代码,涉及cpu/arm1176/start.s,board/开发板目录/lowlevel_init.S和arch/arm/lib/board.c中的board_init_f函数。完成工作如下:
(1)设置CPU为SVC模式,关中断,关看门狗,关MMU;
(2)设置时钟,初始化各硬件控制器;
(3)设置堆栈;
(4)复制(重定位)Uboot到内存中;
(5)跳转到第二阶段代码入口;
阶段二:加载内核镜像并转让控制权给内核,主要用C语言,分两个阶段代码具有更好的可读性与移植性:若对于相同的CPU以及存储设备,要增加外设支持,阶段1的代码可以维护不变,只对阶段2的代码进行修改;若要支持不同的CPU,则基础代码只需在阶段1中修改。
arm/cpu/arm1176/start.S
.globl _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq
以_start标号标识,一开始处设置异常中断向量表,当是冷启动时,直接跳转至对应处进行启动:
系统正常启动,都属于冷启动,程序直接跳转至reset标号处执行。
图片来至:博主------- 一米阳光
我自己代码笔记,基于tiny6410
三、编译环境
基于ARM平台的工具分别为arm-linux-as(汇编器)、arm-linux-gcc(c编译器)、arm-linux-g++(c++编译器)、arm-linux-ld(链接器)四、uboot地址规划设计
当bootloader阶段设计好之后,需要考虑的是镜像存储的地址分配:总镜像保存在什么地方,阶段2对应的镜像会被拷贝到什么地方;内核镜像原先存放在什么地方,bootloader会把它又重新加载到什么地方;具体怎么设计要看处理器和内存情况。
相关文章推荐
- Uboot学习笔记③---(uboot移植及启动过程)
- TQ2440 学习笔记—— 30、移植U-Boot【U-Boot 的启动过程第一阶段源码分析】
- Spring Boot学习笔记03--深入了解SpringBoot的启动过程
- TQ2440 学习笔记—— 31、移植U-Boot【U-Boot 的启动过程第二阶段源码分析】
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 学习笔记--- U-BOOT从启动到引导内核过程分析
- 学习笔记----S3C2440 从NANDFLASH启动的设计原理与过程
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 移植u-boot学习笔记3-----分析启动过程之重定位
- 移植u-boot学习笔记1-----实验及分析启动过程之概述
- Linux 学习笔记_13_2_LAMP环境编译(下) --编译过程及分析
- 移植u-boot学习笔记2-----分析启动过程之内存分布
- TQ2440 学习笔记—— 29、移植U-Boot【U-Boot 的编译、链接过程】
- 学习笔记----linux下编译环境的配置
- Linux学习笔记---RHEL系统启动过程
- 正式学习bootloader,基于u-boot1.1.4(启动流程框架)
- uboot移植,编译及环境变量,启动等方面---from README
- JVM学习笔记(1、 基本结构;2、Java代码编译和执行的整个过程3、内存管理和垃圾回收 4、 内存调优 )
- JVM学习笔记(二)------Java代码编译和执行的整个过程
- C++学习的一些笔记-->2:防止头文件多次导入造成重复编译的方法