APP下载

基于MPC8306的U-Boot启动流程

2019-10-09关志华

电子技术与软件工程 2019年17期
关键词:命令行堆栈语句

文/关志华

1 引言

U-Boot是一款通用型的引导程序,具有良好的兼容性与灵活性,支持PowerPC、X86和ARM等常用系列的处理器。

如需利用PowerPC处理器与Linux系统进行相关设备与产品的开发,必须对U-Boot进行分析与了解。本文以MPC8306为例,对U-Boot的架构与启动流程进行详细分析,MPC8306为Freescale在2010年推出的PowerQUICCⅡPro处理器,具有极高的的性价比与系统稳定性,适合应用于工业及军事设备,具体的系统架构如图1所示。

2 架构简述

如需进行MPC8306的U-Boot移植,必须对其系统架构有一定了解,主要目录介绍如下:

(1)Arch:存放不同型号CPU的库文件。其中,start.S是非常重要的一个文件,贯穿了U-Boot启动的整个流程,主要负责设置系统堆栈以及相关工作方式。

(2)Board:板级配置相关文件。

(3)Common:通用类型的代码文件。

(4)Include:存放头文件的文件夹。子目录 include/configs下与目标板相关的配置头文件是移植过程中经常要修改的文件,可配置目标板的各项参数(如波特率、引导启动参数等)。

3 启动流程

MPC8306的U-Boot启动流程主要分为两个阶段:Stage 1与Stage2。Stage1中,以Start.s文件为基本流程,代码主要由汇编语言组成,也会调用一些C语言;Stage 2主要由C 语言组成,以board.c文件为基本流程,负责完成板级系统的初始化。具体启动流程如图2所示。

图1:MPC8306的系统架构

图2:MPC8306的U-Boot启动流程

3.1 Stage 1

硬件复位完成后,CPU开始读取系统复位向量对应的偏移地址为0x100处的第一条指令,这条指令位于U-Boot中Start.S文件的_Start处。_Start为整个U-Boot的全局入口。

当程序运行到Start.S的bl init_e300_core分支语句时,程序跳转到init_e300_core函数中,这个函数主要进行e300内核的初始化,为系统创建一个干净可靠的初始环境。

内核初始化完成后,需要对启动Rom的绝对地址进行重映射,通过Start.S中的map_flash_by_law1函数和remap_flash_by_law0函数可以完成。

初识化PowerPC内部cache需要通过操作BAT以及TLB来实现,利用Start.S中的setup_bats将IBAT0~7以及DBAT0~7初始化,并禁用TLB。

enable_addr_trans、dcache_enable和lock_ram_in_cache函数负责使能地址翻译与D-Cache,lock_ram_in_cache负责锁定,然后建立堆栈。

堆栈建立完成后,流程跳转到cpu_init.c文件的cpu_init_f()函数。该函数主要负责CPU 寄存器的初始化,尤其是初始化Local Access Windows的值和片选BRx,ORx的值。

执行完CPU寄存器的初始化后,程序返回到Start.S中,并通过分支语句“bl board_init_f”跳转到board.c中的C函数board_init_f()中,为全局变量结构体gd分配内存空间(在global_data.h中可以定义gd_t结构体),并运行初始化序列init_sequence,初始化序列init_sequence主要负责板级硬件相关函数的初始化。

board_init_f()函数之前,U-Boot代码一直在Nor-Flash中运行。内存初始化完成以后,程序返回start.S,然后调用relocate_code()函数完成从Flash到RAM的代码复制,记录目前执行代码的偏移,并跳转到RAM中相应的位置执行。最后还需设置RAM中的堆栈,并跳转到的Stage2。

3.2 Stage2

Stage2的入口点为Start.S的分支语句“bl board_init_r”,由此语句跳转到board.c文件的board_init_r()函数中,并在RAM中运行。该函数主要负责高速缓存器和本阶段相关外设的初始化。主要的子函数如下所示:

mem_malloc_init():内存分配初始化;

cpu_init_r ():初始化CPU的高等级部分,比如QE;

flash_init():初始化Nor Flash,使之支持写入、擦除功能;

env_relocate ():环境变量功能指针从ROM到bd结构体的搬移;

stdio_init ():标准化I/O初始化;

console_init_r():再次初始化控制台串口;

main_loop():主循环函数。

初始化完成后,程序自动跳转到主循环main_loop()函数,检查环境变量中是否定义bootdelay的值,如果已定义就把值读出来,该环境变量值定义了进入U-Boot的等待时间。如果在此时间内没有按键,从串口查询不到按键输入,则执行设置的缺省命令。若有按键输入则进入命令循环,显示命令行模式的交互界面,接受用户从串口输入的命令。在该界面下,每从串行口读入一个命令行,则调用common/main.c中的run_command()函数完成对命令行的解析,发现相符就以命令行中的参数调用相应的函数。

4 结论

本文结合MPC8306的芯片手册与U-Boot源代码详细分析了U-Boot的启动流程,并对其中各源码文件与重要函数的意义进行说明。为U-Boot在MPC8306相关产品板的移植提供了理论基础,能够有效缩短项目的开发时间。

猜你喜欢

命令行堆栈语句
重点:语句衔接
一种基于docker集群的自动评价虚拟命令行实验终端构建及其在类Unix系统教学中的应用
Windows 10新版CMD更新
嵌入式软件堆栈溢出的动态检测方案设计*
基于堆栈自编码降维的武器装备体系效能预测
如何搞定语句衔接题
一种用于分析MCS-51目标码堆栈深度的方法
作文语句实录
基于堆栈的24点游戏解决方案