u-boot分析之两阶段代码分析(三)
目录
- u-boot(三)启动文件
- 1,概述
- 2,uboot第一阶段代码分析:
- 汇编
- 2,uboot第二阶段代码分析
- C:_start_armboot
- C:main_loop
u-boot(三)启动文件
1,概述
本书使用的uboot从nor flash启动,下面以开发板100ask24x0的uboot为例。
uboot属于两阶段的bootloader,第一阶段的文件为cpu/arm920t/start.S和board/100ask24x0/lowlevel_init.S,前者是平台相关的,后者是开发板相关的,主要是汇编实现,主要完成一些依赖于cpu体系结构的初始化,并调用第二阶段的代码;第二阶段的文件从lib_arm/board.c开始,主要是c语言实现,实现更复杂的功能。
2,uboot第一阶段代码分析:
(1)硬件设备初始化
将cpu设为svc模式,关闭watchdog,设置时钟,关闭MMU,CACHE,代码在cpu/arm920t/start.S中。
(2)为加载bootloader的第二阶段代码准备RAM空间
初始化RAM空间,通过在调用start.S中调用lowlevel_init函数来设置存储控制器,使得sdram可用,代码在board/100ask24x0/lowlevel_init.S中。
(3)复制bootloader的第二阶段代码到RAM空间中
将整个uboot代码(包括第一、第二阶段)都复制到SDRAM中,在cpu/arm920t/start.S中实现。(注意:100ask24x0改为用c函数实现的)。
(4)设置好栈
栈的设置灵活性很大,只要让sp指向一段没有使用的内存即可,下面分析可以看到内存的使用情况。
(5)跳转到第二阶段代码的C入口点
跳转之前清除bss段(初始值为0、无初始值的全局变量,静态变量放在bss段),c函数的运行环境准备好后,通过调用lib_arm/board.c中的start_armboot跳到c函数的入口点,这是第二阶段的入口点。
汇编:_start
cpu/arm920t/start.S
u-boot也是一个牛逼的单片机程序,所以也就需要:
- 硬件相关初始化
- 看门狗
- 时钟
- sdram
- nand copy程序
- 设置sp
- 接下去就是读取内核,启动内核等
程序实际的步骤是:
1.set the cpu to SVC32 mode
2.turn off the watchdog
3.mask all IRQs
4.clock_init board\100ask24x0\boot_init.c
5.cpu_init_crit do sys-critical inits only at reboot,not when booting from ram!判断
是不是从内部ram启动还是仿真直接烧写到链接地址,如果不在正确的加载地址的话,执行cpu_init_critcpu_init_crit执行SDRAM初始化flush v4 I/D caches,disable MMU stuff and caches,lowlevel_init 这个会去初始化sdram,这个函数在lowlevel_init.S in your board directory也就是board\100ask24x0\lowlevel_init.S
6.Set up the stack
7.relocate CopyCode2Ram中自动识别当前是nor还是nand启动,nand启动时自动cp到内部ram中运行,所以可写,CopyCode2Ram位于board\100ask24x0\boot_init.c
8.bss段清零
9.调用C函数 _start_armboot
堆栈设置如下
0x33F80000 | uboot程序 |
---|---|
·=-CFG_MALLOC_LEN | malloc area |
.=-CFG_GBL_DATA_SIZE | bdinfo |
.=-CONFIG_STACKSIZE_IRQ | IRQ 的栈 |
.=-CONFIG_STACKSIZE_FIQ | FRQ的栈 |
.=-12 | leave 3 words for abort-stack |
sp的初始位置 |
内存图:
2,uboot第二阶段代码分析
(1)初始化本阶段要使用到的硬件设备
(2)检测系统内存映射(memory map)
(3)uboot命令的格式
(4)为内核设置启动参数
第二阶段从lib_arm/board.c中的start_armboot函数开始,程序流程如下:
C:_start_armboot
文件路径:lib_arm\board.c
,这里就是u-boot执行C代码的地方了.
- 分配了一个gd的结构体内存
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));//在这里,_armboot_start=_start,根据链接脚本,这也就是代码段的起始=0x33F80000
//也就是指向了内存图128的地方了
- 执行init_sequence数组里预先定义的一些初始化函数
board_init
中设置了gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
,设置了一个参数gd->bd->bi_boot_params = 0x30000100;
这个就是启动内核参数的地址
- flash_init、nand_init:flash/nand 初始化
- 堆栈初始化
- env_relocate:环境变量的设置存储(环境变量来源有两种:一种是代码写死(也就是默认),一种在FLASH上保存,uboot启动后会检查flash上是否有可用的环境变量,有就用flash上的,否则使用默认)
main_loop:
进入主循环
代码摘要
void start_armboot (void)
{
//-----/* Pointer is writable since we allocated a register for it */gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
//----- //函数指针,初始化设备for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) {hang ();}}
//---- flash初始化,识别
#ifndef CFG_NO_FLASH/* configure available FLASH banks */size = flash_init ();display_flash_config (size);
#endif /* CFG_NO_FLASH */
---- nand初始化
#if (CONFIG_COMMANDS & CFG_CMD_NAND)puts ("NAND: ");nand_init(); /* go init the NAND */
#endif
//------//分配堆/* armboot_start is defined in the board-specific linker script */mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
//-----//uboot的环境变量/* initialize environment */env_relocate ();
//-----//经过一系列的初始化/* main_loop() can return to retry autoboot, if so just run it again. */for (;;) {main_loop ();}init_fnc_t *init_sequence[] = {cpu_init, /* basic cpu dependent setup */board_init, /* basic board dependent setup */interrupt_init, /* set up exceptions */env_init, /* initialize environment */init_baudrate, /* initialze baudrate settings */serial_init, /* serial communications setup */console_init_f, /* stage 1 init of console */display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)checkboard, /* display board info */
#endifdram_init, /* configure available RAM banks */display_dram_config,NULL,
};int board_init (void)
{---/* support both of S3C2410 and S3C2440, by www.100ask.net */if (isS3C2410){/* arch number of SMDK2410-Board */gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;}else{/* arch number of SMDK2440-Board */gd->bd->bi_arch_number = MACH_TYPE_S3C2440;}/* adress of boot parameters */gd->bd->bi_boot_params = 0x30000100;}
C:main_loop
common/main.c
main_loop两种选择:
①在bootdelay减到零之前敲下任意键将进入uboot控制界面(命令行模式),不过这里100ask24x0自定义一个menu命令,所以此时进入的是自己实现的菜单模式,可输入‘q’退出此模式转而进入命令行模式,readline (CFG_PROMPT)不断接收串口传过来的命令,run_command (lastcommand, flag)执行这些命令 。
②若倒计时结束前没有敲下任意键,将根据参数bootcmd来启动内核,getenv ("bootcmd")获得参数bootcmd值,可知bootcmd = read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0,其中read.jffs2和bootm均为uboot命令,所以uboot核心是命令,要继续分析uboot是如何将内核从flash上搬到sdram并启动内核,必须深入分析这些命令才能清楚。
内核启动
这里实现了u-boot的倒计时,有打印命令,获取环境变量等,最关键的代码是
s = getenv ("bootcmd");
if(倒计时结束)
{printf("Booting Linux ...\n"); run_command (s, 0);}
实际的环境变量是bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0
,读取内核,启动内核
菜单处理(自定义实现)
如果倒计时结束前输入了空格,进入命令模式run_command("menu", 0);
命令处理
- 死循环
- 读取串口输入
len = readline (CFG_PROMPT);
- 执行命令
rc = run_command (lastcommand, flag);
转载:
https://www.cnblogs.com/zongzi10010/p/10023676.html
u-boot分析之两阶段代码分析(三)相关推荐
- 浅谈两阶段提交和三阶段提交
本文主要分为三个部分 第一部分阐述两阶段提交的原理和优缺点. 第二部分阐述三阶段提交的原理和优缺点. 第三部分阐述如何解决业务中最终一致性的问题. 一.两阶段提交 两阶段提交方法是用于分布式事务中用来 ...
- 分布式事务:两阶段提交与三阶段提交
两阶段提交与三阶段提交 分布式事务 二阶段提交 请求阶段 提交阶段 举例 故障分析 柜员侧出现故障或拒绝Proposal 第一阶段经理侧出现故障 第二阶段经理侧出现故障 二阶段提交存在的问题 三阶段提 ...
- 两阶段提交和三阶段提交
分布式提交的问题 在分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上. 在数据有多份副本的情况下,如果网络.服务器或者软件出现故障,会 ...
- linux pl320 mbox控制器驱动分析-(3) pl320驱动代码分析
linux pl320 mbox控制器驱动分析-(3)pl320驱动代码分析 1 pl320 mbox控制器宏定义 2 初始化接口 3 ipc_handler mbox中断处理函数 4 数据的收发 4 ...
- 两阶段提交与三阶段提交
两阶段提交是什么? 两阶段提交非常有名,其原因主要有两点: 一个是历史很悠久: 二是其定义是很模糊的,它首先不是一个协议,更不是一个规范,而仅仅是作为一个概念存在,故从传统的关系统数据库一致的最新的 ...
- CAP原理,分布式一致性算法,两阶段提交,三阶段提交,Paxos,Raft,zookeeper的选主过程,zab协议,顺序一致性,数据写入流程,节点状态,节点的角色
我们知道,一般在分布式应用都有CAP准则: C Consistency, 一致性,分布式中的各个节点数据保持一致 A availability 可用性,任何时刻,分布式集群总是能够提供服务 P par ...
- 分布式两阶段提交和三阶段提交
随着大型网站的各种高并发访问.海量数据处理等场景越来越多,如何实现网站的高可用.易伸缩.可扩展.安全等目标就显得越来越重要. 为了解决这样一系列问题,大型网站的架构也在不断发展.提高大型网站的高可用架 ...
- 分布式架构--两阶段提交和三阶段提交
在分布式系统中,著有CAP理论,该理论由加州大学伯克利分校的Eric Brewer教授提出,该理论阐述了在一个分布式系统中不可能同时满足一致性(Consistency).可用性(Availabilit ...
- android 触摸屏驱动分析,Android 触摸屏驱动代码分析(ADC 类型触摸屏 CPU:s3c
Android 2.1 farsight version for s5pc100 File Name: s3c-ts.c 1 简介 1.1 本例基于s5pc100 ...
最新文章
- python bind_Python bind-允许同时按下多个键
- java排列组合算法优缺点,一招彻底弄懂!
- ios 上传图片失败 小程序_微信小程序ios端 使用ajaxSubmit上传图片失败,android没问题...
- Matplotlib - plot用例
- paip.批处理清理java项目冗余jar的方法
- centos6.5 升级oracle 10.2.0.5.0,CentOS5上升级ORACLE到10.2.0.4时,检测操作系统失败的解决方法...
- OCP 12c最新考试原题及答案(071-7)
- 2018-2019-2 网络对抗技术 20165322 Exp9 Web安全基础
- 机器学习 | 数学基础
- 遥控器鼠标模式切换 android 4.4
- 2023考研高数思维导图
- java 提交mac地址栏_Mac系统快捷键大全 - 米扑博客
- 后端API接口的错误信息返回规范
- mxgraph.js实现Topo图
- 安卓TextView实现文字跑马灯(失去焦点可用)
- Windows 9x、2K、XP、2003注册表大全
- python逐行写入文件_Python文件逐行写入
- 1029:三角形的判定
- python数据分析面试题_面试题——Python数据分析与应用(补充:简答)
- 【Python测试】期末测试