嵌入式u-boot浅析
来源:互联网 发布:剃头软件叫什么 编辑:程序博客网 时间:2024/05/21 08:50
u-boot主要目的是为操作系统的运行提供准备工作,根据其运行流程简单的分为四部分:_start、board_init_f、relocate_code和board_init_r。其中_start和relocate_code是运行在flash上,而board_init_f和board_init_r是运行于DRAM上的。
下面对其四个部分进行简单的介绍分析:
1、_start
这是u-boot的起始部分,程序从/u-boot/cpu/mips/start.S文件中的_start代码段开始执行的。由于此时内存未初始化,所以该部分是运行于flash上的。其主要的内容有:
(1) 对cpu相关寄存器的初始化;
(2) TLB(Translation Lookaside Buffer)初始化;
(3) 初始化一块临时内存作为栈空间scratch memory,为内存初始化之前调用c语言使用;
(4) 初始化全局符号表指针GOT pointer;
完成上述初始化后,将会申请1MB的内存空间用于存放u-boot代码,并初始化这一内存空间。然后跳转到relocate_code。
3、relocate_code
该部分主要是将u-boot拷贝到上面申请的1MB内存空间中,然后跳转到board_init_r。
4、board_init_r
该部分主要是完成后续环境的初始化,如堆空间的分配、串口初始化和网卡初始化等。到目前为止u-boot启动基本完成,已为操作系统运行准备了必要的环境。
5、调试
u-boot的调试方法有很多种,下面介绍两种方式:使用led灯(即点灯)、利用一个已调试完成的u-boot引导调试另一个u-boot等。
在调试过程中在串口未初始化时可以使用点灯的方式跟踪,如果串口已初始化而未输出调试信息,可以关注对串口的配置是否正确。
(1)点灯
所谓的点灯既是在串口设备未初始化之前,驱动led灯的闪烁来判断程序的执行流程来完成调试。使用点灯调试首先需要了解到cpu芯片和led的连接方式,以及所使用的寄存器等。根据pcb图可以得知cpu芯片和led是通过GPIO的进行连接的,再从cpu芯片厂商提供的datasheet查询操作GPIO的相关寄存器和方法。
点灯可以分为两种方式:一种是使用汇编指令进行点灯操作,具体的汇编指令依赖所使用的cpu架构,本文的cpu架构为MIPS;另一种是使用u-boot提供的相关C语言接口进行点灯操作。下面均以GPIO 10的操作分别进行简单介绍:
1)汇编指令点灯操作
2)C语言接口点灯操作
(2)u-boot引导u-boot
使用u-boot调试u-boot的方式主要是通过已调试完成的u-boot去调试一个待调试的u-boot,本文使用已调试完成的first_uboot作为引导。调试的方式分为两种:
1)待first_uboot启动完成之后,使用其提供的命令(如go)跳转到待调试的u-boot;
2)在first_uboot刚启动时,通过控制汇编跳转指令跳转到待调试的u-boot。
上述两种方式都是为了在调试u-boot过程中减少将flash摘除到擦写器中擦写的次数,提高调试效率。
两者的调试方式虽然类似,但是使用的时期具有一定的区别。第一种方式通过go命令跳转说明first_uboot已经将硬件环境进行了相关的初始化,所以跳转执行时会将待调试的u-boot拷贝到内存中执行,这将导致待调试u-boot初始化硬件的过程不完整。所以建议第一种调试方式主要用于进行初步调试,查看一些不依赖硬件的相关参数。第二种方式可以通过控制跳转点的位置来确保safe_loader还未硬件初始化就跳转到待调试u-boot,这样就能较为完整的调试u-boot,过程中需要结合上述的点灯等操作。虽然这样跳转能确保大部分硬件得到初始化,但是仍然会有一定的问题,目前发现的问题是该cpu为双核,但是通过这样的引导之后加载linux内核未能将第二颗核启动。调试完成之后只使用该u-boot可以顺利将第二颗核启动。
1)go命令跳转
使用go命令跳转进行调试时需要确定已调试的u-boot是否支持该命令,以及待调试u-boot中的相关配置需要进行调整。本文使用已调试完成的first_uboot可以通过命令go跳转到待调试的u-boot进行调试。其中待调试的u-boot需要修改顶层Makefile中的指定其在flash的位置,本文改为0xbec30000。
从上图可以看到需要将first_uboot和u-boot烧录到flash中,先启动first_uboot,完成之后执行go命令跳转到待调试的u-boot中。在调试过程中需要打开u-boot中的相关调试开关,也可以在关键地方增加相应调试信息。
2)汇编指令跳转
根据pcb图并结合u-boot提供的启动汇编代码可以得出,可以使用设备上的RST键进行跳转。从如下截图中可以看出RST键是通过GPIO连接到CPU芯片的GPIO 5号脚。
据上面的分析可以设计的调试方式是在启动first_uboot时按RST键则跳转到调试的u-boot,否则继续执行。如下的汇编代码实现了这一调试需求,即在first_uboot刚加载时读取GPIO 5的值,用于判断执行分支。注意跳转指令所使用的地址,j指令为直接跳转,其跳转的地址范围是28位即最大跳转地址空间为256MB;如果跳转地址大过该范围,需要使用寄存器跳转方式,如jr t1。
下面对其四个部分进行简单的介绍分析:
1、_start
这是u-boot的起始部分,程序从/u-boot/cpu/mips/start.S文件中的_start代码段开始执行的。由于此时内存未初始化,所以该部分是运行于flash上的。其主要的内容有:
(1) 对cpu相关寄存器的初始化;
(2) TLB(Translation Lookaside Buffer)初始化;
(3) 初始化一块临时内存作为栈空间scratch memory,为内存初始化之前调用c语言使用;
(4) 初始化全局符号表指针GOT pointer;
(5) 使用跳转命令跳转到board_init_f;
2、board_init_f该部分是在上面申请的临时内存空间中运行的,主要是内存的初始化及整个寻址空间的部分初始化。其主要是循环调用init_sequence函数指针数组中的成员,如下所示
init_fnc_t *init_sequence[] = { octeon_boot_bus_init, // GPIO使能、flash空间映射及大小设置等; timer_init, env_init, early_board_init, //cpu主频、板子型号等初始化; init_baudrate, //串口频率配置; serial_init, //串口初始化; console_init_f, display_banner, init_dram, //内存初始化; checkboard, //一些检测; init_func_ram, switch_init, //初始化switch的配置; NULL,};
完成上述初始化后,将会申请1MB的内存空间用于存放u-boot代码,并初始化这一内存空间。然后跳转到relocate_code。
3、relocate_code
该部分主要是将u-boot拷贝到上面申请的1MB内存空间中,然后跳转到board_init_r。
4、board_init_r
该部分主要是完成后续环境的初始化,如堆空间的分配、串口初始化和网卡初始化等。到目前为止u-boot启动基本完成,已为操作系统运行准备了必要的环境。
5、调试
u-boot的调试方法有很多种,下面介绍两种方式:使用led灯(即点灯)、利用一个已调试完成的u-boot引导调试另一个u-boot等。
在调试过程中在串口未初始化时可以使用点灯的方式跟踪,如果串口已初始化而未输出调试信息,可以关注对串口的配置是否正确。
(1)点灯
所谓的点灯既是在串口设备未初始化之前,驱动led灯的闪烁来判断程序的执行流程来完成调试。使用点灯调试首先需要了解到cpu芯片和led的连接方式,以及所使用的寄存器等。根据pcb图可以得知cpu芯片和led是通过GPIO的进行连接的,再从cpu芯片厂商提供的datasheet查询操作GPIO的相关寄存器和方法。
点灯可以分为两种方式:一种是使用汇编指令进行点灯操作,具体的汇编指令依赖所使用的cpu架构,本文的cpu架构为MIPS;另一种是使用u-boot提供的相关C语言接口进行点灯操作。下面均以GPIO 10的操作分别进行简单介绍:
1)汇编指令点灯操作
#if 1 nop dli t0, 0x8001070000000850 /* GPIO 10 */ ld t1, 0(t0) or t1, 1 sd t1, 0(t0) nop ld t1, 1 nopled: ld t1, 1 bne zero, t1, led nop#endif
2)C语言接口点灯操作
void gpio_set(int bit)//bit为GPIO号{ uint64_t val = read_csr(GPIO_BIT_CFGX(bit)); write_csr(GPIO_BIT_CFGX(bit), val | 1); val = read_csr(GPIO_BOOT_ENA); write_csr(GPIO_BOOT_ENA, val & ~(1<<bit)); write_csr(GPIO_TX_SET, 1 << bit); }
(2)u-boot引导u-boot
使用u-boot调试u-boot的方式主要是通过已调试完成的u-boot去调试一个待调试的u-boot,本文使用已调试完成的first_uboot作为引导。调试的方式分为两种:
1)待first_uboot启动完成之后,使用其提供的命令(如go)跳转到待调试的u-boot;
2)在first_uboot刚启动时,通过控制汇编跳转指令跳转到待调试的u-boot。
上述两种方式都是为了在调试u-boot过程中减少将flash摘除到擦写器中擦写的次数,提高调试效率。
两者的调试方式虽然类似,但是使用的时期具有一定的区别。第一种方式通过go命令跳转说明first_uboot已经将硬件环境进行了相关的初始化,所以跳转执行时会将待调试的u-boot拷贝到内存中执行,这将导致待调试u-boot初始化硬件的过程不完整。所以建议第一种调试方式主要用于进行初步调试,查看一些不依赖硬件的相关参数。第二种方式可以通过控制跳转点的位置来确保safe_loader还未硬件初始化就跳转到待调试u-boot,这样就能较为完整的调试u-boot,过程中需要结合上述的点灯等操作。虽然这样跳转能确保大部分硬件得到初始化,但是仍然会有一定的问题,目前发现的问题是该cpu为双核,但是通过这样的引导之后加载linux内核未能将第二颗核启动。调试完成之后只使用该u-boot可以顺利将第二颗核启动。
1)go命令跳转
使用go命令跳转进行调试时需要确定已调试的u-boot是否支持该命令,以及待调试u-boot中的相关配置需要进行调整。本文使用已调试完成的first_uboot可以通过命令go跳转到待调试的u-boot进行调试。其中待调试的u-boot需要修改顶层Makefile中的指定其在flash的位置,本文改为0xbec30000。
从上图可以看到需要将first_uboot和u-boot烧录到flash中,先启动first_uboot,完成之后执行go命令跳转到待调试的u-boot中。在调试过程中需要打开u-boot中的相关调试开关,也可以在关键地方增加相应调试信息。
2)汇编指令跳转
根据pcb图并结合u-boot提供的启动汇编代码可以得出,可以使用设备上的RST键进行跳转。从如下截图中可以看出RST键是通过GPIO连接到CPU芯片的GPIO 5号脚。
据上面的分析可以设计的调试方式是在启动first_uboot时按RST键则跳转到调试的u-boot,否则继续执行。如下的汇编代码实现了这一调试需求,即在first_uboot刚加载时读取GPIO 5的值,用于判断执行分支。注意跳转指令所使用的地址,j指令为直接跳转,其跳转的地址范围是28位即最大跳转地址空间为256MB;如果跳转地址大过该范围,需要使用寄存器跳转方式,如jr t1。
#define GPIO_BIT 5 //GPIO 引脚号#define GPIO_RX_DAT 0x8001070000000880 //GPIO状态寄存器dli t0, GPIO_RX_DATld t1, 0(t0)andi t1, (0x1 << GPIO_BIT)bne zero, t1, boot_contnopli t1, 0xbfc30000 //跳转地址赋值;j t1 // 跳转到指定地址,即调试u-boot的起始地址
阅读全文
0 0
- 嵌入式u-boot浅析
- U-Boot 环境变量浅析
- 嵌入式 U-Boot
- u-boot bootm命令浅析
- u-boot bootm命令浅析
- 嵌入式 u-boot裁剪备忘
- 什么是u-boot【嵌入式1】
- U-Boot 编译(嵌入式U-BOOT,kernel编译)
- u-boot配置和编译过程浅析
- u-boot 浅析从Makefile开始
- U-boot .balignl 16,0xdeadbeef浅析
- ARM U-Boot SPL过程浅析
- 嵌入式系统搭建之一u-boot移植
- u-boot 学习 /*嵌入式博客3_6*/
- 【嵌入式】探究bootloader,分析u-boot源码
- 【嵌入式】FS2410移植U-Boot-1.1.6
- 嵌入式软件组成及u-boot介绍
- 【嵌入式】探究bootloader,分析u-boot源码
- 存储过程、定时事件的使用
- Android应用程序的Activity启动过程
- python-文件操作及os模块常用函数
- Android网络数据传输中的GZIP压缩
- js 格式化货币
- 嵌入式u-boot浅析
- JVM GC算法
- 正则验证手机号和电话号码
- 使用github详细介绍
- 申请和device不再同一个numa节点的memory
- ES6学习笔记---二进制数组(概念)
- Ubuntu 设置mysql 远程访问
- lodash difference 函数demo
- js中必须用分号的地方——由一个题目引起的思考