全志A10 Bootload加载过程分析

A10的启动过程大概可分为5步:BootRom,SPL,Uboot,Kernel,RootFileSystem。本文只关注镜像的加载过程,分析RootRom->SPL->Uboot的启动流程。
系统上电后,ARM处理器在复位时从地址0x000000开始执行指令,把板上ROM或Flash映射到这一地址。A10将启动设备选择程序固化在CPU内部的一个32KB ROM中,默认的启动时序为SD Card0,NAND FLASH,SD Card2,SPI NOR FLASH。另外通过外部的一个启动选择引脚可以使其跳转到USB启动模式。通常情况下,启动选择引脚状态连接50K内部上拉电阻。在上电后,执行存储在ROM中的启动代码,将自动检测启动选择引脚状态。只有当该引脚状态为低电平时选择USB启动模式。
启动设备选择程序的流程图:
在选择启动设备后将加载并执行bootload程序,CPU通过拷贝或映射bootload程序到内存,然后执行bootload的第一条指令。通过阅读官方的uboot烧写方法,发现A10通过uboot引导系统,但却没有加载整个uboot,而是在此之前先载入了uboot SPL。什么是SPL?通过查阅uboot的官网资料得知,SPL是一个迷你版的uboot,全拼为Second Program Loader。适用于SOC的内部SROM<64K的情况,用它来加载完整的uboot程序到SDROM,并通过完整uboot加载内核来启动系统。
SPL程序流程如下:
1.初始化ARM处理器
2.初始化串口控制台
3.配置时钟和最基础的分频
4.初始化SDRAM
5.配置引脚多路复用功能
6.启动设备初始化(即上面选择的启动设备)
7.加载完整的uboot程序并转交控制权
搞清楚了上面的概念,可以知道Cubieboard出厂已经烧写了NandFlash中的程序,即在启动选择时使用的是NandFlash。现在根据全志A10上的步骤,我们尝试用SDC1(即Cubieboard上卡槽中的TF卡)来启动系统。
下载并编译uboot
#git clone https://github.com/linux-sunxi/u-boot-sunxi.git
#cd u-boot-sunxi
#export CROSS_COMPILE=arm-linux-gnueabihf-
#make cubieboard
为TF卡烧写引导程序
#dd if=/dev/zero of=/dev/sdb bs=1M count=1 # 清空SD卡(包括分区表)
尝试不建立分区表,直接烧写引导程序,无法启动系统。
因此按需求给TF卡分区,我只创建了唯一一个200M主分区,此处不详述分区过程,下面是我使用的TF卡的分区表信息。
$ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 1977 MB, 1977614336 bytes
52 heads, 30 sectors/track, 2475 cylinders, total 3862528 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Device Boot Start End Blocks Id System
/dev/sdb1 2048 411647 204800 83 Linux
通过A10相关资料,通过以下2条命令烧写spl和uboot到指定位置,暂时不清楚如何确定这2个读取位置。
#dd if=spl/sunxi-spl.bin of=/dev/sdb bs=1024 seek=8
#dd if=u-boot.bin of=/dev/sdb bs=1024 seek=32
烧写完成后插入TF卡到CB的卡槽中,连接USB转TTL串口线,打开串口终端,上电。
串口打印信息如下:
U-Boot SPL 2012.10-04277-g7aa9f04 (Mar10 2013 - 00:36:40)
DRAM: 1024MB
SUNXI SD/MMC:0


U-Boot 2012.10-04277-g7aa9f04 (Mar10 2013 - 00:36:40) Allwinner Technology

CPU: SUNXI Family
Board: Cubieboard
I2C: ready
DRAM: 1 GiB
MMC: SUNXI SD/MMC:0
*** Warning- bad CRC, using default environment

In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0 

** Unable to use mmc0:1for fatload **
Loading file "uEnv.txt" from mmc device 0:1
Failed to mount ext2 filesystem...
** Bad ext2 partitionor disk - mmc0:1**
ext2load - load binary file from a Ext2 filesystem

Usage:
ext2load <interface><dev[:part]> [addr] [filename] [bytes]
- load binary file 'filename' from 'dev' on 'interface'
to address 'addr' from ext2 filesystem
Loading file "boot/uEnv.txt" from mmc device 0:1
Failed to mount ext2 filesystem...
** Bad ext2 partitionor disk - mmc0:1**
ext2load - load binary file from a Ext2 filesystem

Usage:
ext2load <interface><dev[:part]> [addr] [filename] [bytes]
- load binary file 'filename' from 'dev' on 'interface'
to address 'addr' from ext2 filesystem

** Unable to use mmc0:1for fatload **
Loading file "boot.scr" from mmc device 0:1
Failed to mount ext2 filesystem...
** Bad ext2 partitionor disk - mmc0:1**
ext2load - load binary file from a Ext2 filesystem

Usage:
ext2load <interface><dev[:part]> [addr] [filename] [bytes]
- load binary file 'filename' from 'dev' on 'interface'
to address 'addr' from ext2 filesystem
Loading file "boot/boot.scr" from mmc device 0:1
Failed to mount ext2 filesystem...
** Bad ext2 partitionor disk - mmc0:1**
ext2load - load binary file from a Ext2 filesystem

Usage:
ext2load <interface><dev[:part]> [addr] [filename] [bytes]
- load binary file 'filename' from 'dev' on 'interface'
to address 'addr' from ext2 filesystem

** Unable to use mmc0:1for fatload **
sun4i#
通过串口信息可以看到SPL和Uboot已经成功加载,uboot最后通过ext2load命令读取uEnv.txt和boot.scr文件失败后退回控制台。
下面通过源码分析SPL载入完整Uboot的过程。
/u-boot-sunxi/common/spl/spl.c - board_init_r
void board_init_r(gd_t *dummy1, ulong dummy2)
{
u32 boot_device;
debug(">>spl:board_init_r()\n");
puts(">>spl:board_init_r()\n");

#ifdef CONFIG_SYS_SPL_MALLOC_START
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
CONFIG_SYS_SPL_MALLOC_SIZE);
#endif

timer_init();

#ifdef CONFIG_SPL_BOARD_INIT
spl_board_init();
#endif

boot_device = spl_boot_device(); //检测启动设备,此处返回BOOT_DEVICE_MMC1
debug("boot device - %d\n", boot_device);
switch (boot_device) {
#ifdef CONFIG_SPL_RAM_DEVICE
case BOOT_DEVICE_RAM:
spl_ram_load_image();
break;
#endif
#ifdef CONFIG_SPL_MMC_SUPPORT
case BOOT_DEVICE_MMC1:
case BOOT_DEVICE_MMC2:
case BOOT_DEVICE_MMC2_2:
spl_mmc_load_image(); //通过mmc读取image
break;
#endif
#ifdef CONFIG_SPL_NAND_SUPPORT
case BOOT_DEVICE_NAND:
spl_nand_load_image();
break;
#endif
#ifdef CONFIG_SPL_NOR_SUPPORT
case BOOT_DEVICE_NOR:
spl_nor_load_image();
break;
#endif
#ifdef CONFIG_SPL_YMODEM_SUPPORT
case BOOT_DEVICE_UART:
spl_ymodem_load_image();
break;
#endif
#ifdef CONFIG_SPL_SPI_SUPPORT
case BOOT_DEVICE_SPI:
spl_spi_load_image();
break;
#endif
#ifdef CONFIG_SPL_ETH_SUPPORT
case BOOT_DEVICE_CPGMAC:
#ifdef CONFIG_SPL_ETH_DEVICE
spl_net_load_image(CONFIG_SPL_ETH_DEVICE);
#else
spl_net_load_image(NULL);
#endif
break;
#endif
default:
debug("SPL: Un-supported Boot Device\n");
hang();
}

switch (spl_image.os) {
case IH_OS_U_BOOT:
debug("Jumping to U-Boot\n");
break;
#ifdef CONFIG_SPL_OS_BOOT
case IH_OS_LINUX:
debug("Jumping to Linux\n");
spl_board_prepare_for_linux();
jump_to_image_linux((void *)CONFIG_SYS_SPL_ARGS_ADDR);
#endif
default:
debug("Unsupported OS image.. Jumping nevertheless..\n");
}
jump_to_image_no_args();
}
u-boot-sunxi/arch/arm/cpu/armv7/sunxi/board.c - spl_boot_device
u32 spl_boot_device(void) {

u32 cfg;

#ifdef CONFIG_SPL_NOR_SUPPORT
/* TODO */
#endif

#ifdef CONFIG_SPL_MMC_SUPPORT
cfg = sunxi_gpio_get_cfgpin(SUNXI_GPC(7));
if( cfg == SUNXI_GPC7_SDC2_CLK )
return BOOT_DEVICE_MMC2;
#endif

#ifdef CONFIG_SPL_NAND_SUPPORT
cfg = sunxi_gpio_get_cfgpin(SUNXI_GPC(2));
if( cfg == SUNXI_GPC2_NCLE )
return BOOT_DEVICE_NAND;
#endif

#ifdef CONFIG_SPL_MMC_SUPPORT
cfg = sunxi_gpio_get_cfgpin(SUNXI_GPF(2));
if( cfg == SUNXI_GPF2_SDC0_CLK )
return BOOT_DEVICE_MMC1;
#endif

/* if we are here, something goes wrong. Fall back on MMC */
return BOOT_DEVICE_MMC1;
}
启动设备是通过读取连接相应设备的GPIO状态来判断的,但在上述条件下执行该段代码时并没有成功检测到设备,直到最后返回BOOT_DEVICE_MMC1。
u-boot-sunxi/drivers/mmc/spl_mmc.c - spl_mmc_load_image
void spl_mmc_load_image(void)
{
struct mmc *mmc;
int err;
u32 boot_mode;

mmc_initialize(gd->bd);
/* We register only one device. So, the dev id is always 0 */
mmc = find_mmc_device(0);
if (!mmc) {
puts("spl: mmc device not found!!\n");
hang();


err = mmc_init(mmc);
if (err) {
printf("spl: mmc init failed: err - %d\n", err);
hang();

boot_mode = spl_boot_mode(); // sunxi的代码在此处直接返回了MMCSD_MODE_RAW
if (boot_mode == MMCSD_MODE_RAW) {
debug("boot mode - RAW\n");
mmc_load_image_raw(mmc);
#ifdef CONFIG_SPL_FAT_SUPPORT
else if (boot_mode == MMCSD_MODE_FAT) {
debug("boot mode - FAT\n");
mmc_load_image_fat(mmc);
#endif
else {
puts("spl: wrong MMC boot mode\n");
hang();

}
u-boot-sunxi/drivers/mmc/spl_mmc.c - mmc_load_image_raw
static void mmc_load_image_raw(struct mmc*mmc)
{
u32 image_size_sectors, err;
const struct image_header *header;

header = (struct image_header*)(CONFIG_SYS_TEXT_BASE -
sizeof(struct image_header));

/* read image header to find the image size & load address */
err = mmc->block_dev.block_read(0,
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1,
(void *)header);

if (err <= 0)
goto end;

spl_parse_image_header(header);

/* convert size to sectors - round up */
image_size_sectors = (spl_image.size + mmc->read_bl_len- 1/
mmc->read_bl_len;

/* Read the header too to avoid extra memcpy */
err = mmc->block_dev.block_read(0,
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
image_size_sectors, (void *)spl_image.load_addr); //此处确定了Uboot读取位置

end:
if (err <= 0) {
printf("spl: mmc blk read err - %d\n", err);
hang();
}
}
u-boot-sunxi/include/configs/sunxi-common.h
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR (64)/* 32KB offset */
#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS (400)/* 200KB, enough for a full u-boot.bin */
通过CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR确定了我们把完整的uboot写入到TF卡从32K位置开始。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433165.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android老 电池,为什么安卓手机不会因为电池的老化而降频呢?

前段时间&#xff0c;苹果手机的降频事件也是闹的沸沸扬扬&#xff0c;库克也为此进行了公开道歉&#xff0c;各位的吃瓜群众也是看的不亦乐乎&#xff0c;于是&#xff0c;也有不少的小伙伴会问&#xff1a;“为什么安卓手机不会因为电池的老化而降频&#xff1f;”今天&#…

android 5.0.1 libdvm.so,Android逆向进阶—— 脱壳的奥义(基ART模式下的dump)

本文作者&#xff1a;i春秋作家HAI_ZHU000 前言市面上的资料大多都是基于Dalvik模式的dump&#xff0c;所以这此准备搞一个ART模式下的dump。Dalvik模式是Android 4.4及其以下采用的模式&#xff0c;之后到了Android 5.0 之后就是ART模式&#xff0c;关于这两个模式的详细内容&…

android+3.0新加的动画,Android动画片

使用Android两年多了&#xff0c;工作中的动画也动能应付&#xff0c;自认为Android中的动画自己也能用个八九不离十&#xff0c;结果我在学习[Periscope点赞效果](http://www.jianshu.com/p/03fdcfd3ae9c)的时候发现动画的这些高级功能我从没用过、也没见过&#xff0c;静下来…

在线打开html文件,html是什么文件?html文件怎么打开?

html是什么&#xff1f;html即超文本标记语言&#xff0c;现在大多网页都是html的格式。而所谓的html文件是一种超文本文件&#xff0c;其中超文本可以是图片或音乐等非文字元素&#xff0c;使用很广泛。但是很多用户都不太明白html是什么文件&#xff1f;也不清楚html文件要如…

gsoap使用心得! (win32)

最近换了个工作环境&#xff0c;现在在大望路这边上班&#xff0c;呵&#xff0c;刚上班接到的任务就是熟悉gsoap&#xff01;废话少说&#xff0c;现在开始gSoap学习&#xff01;gSOAP是一个夸平台的&#xff0c;用于开发Web Service服务端和客户端的工具&#xff0c;在Window…

html怎么置顶导航栏,css怎么实现滚动页面导航栏固定在顶部

css怎么实现滚动页面导航栏固定在顶部(吸顶效果)功能&#xff1a;当网页向下滚动时&#xff0c;导航栏一直在固定在顶部一、css设置这里主要用到css中position中的relative与fixed&#xff1b;其中relative是生成相对定位的元素&#xff0c;相对于其正常位置进行定位。fixed是生…

numpy读取csv_Numpy——IO操作与数据处理

一、问题&#xff1f;大多数数据并不是我们自己构造的&#xff0c;存在文件当中。我们需要工具去获取&#xff0c;但是Numpy其实并不适合去读取处理数据&#xff0c;这里我们了解相关API&#xff0c;以及Numpy不方便的地方即可。二、Numpy读取genfromtxt(fname[, dtype, commen…

android 中radiogroup滑动切换,巧妙实现缺角radiogroup控制多个fragment切换和滑动

在android开发中&#xff0c;用一个radiogroup控制多个fragment切换是十分常见的需求。但是如果fragment是一个ListView&#xff0c;如何保证滑动的时候通过缺角可以看到下面的listview是一个难点。直接上图:(1)完美效果(2)较差效果另外&#xff0c;不妨假设缺角的高度是5dp&am…

荣耀智慧屏评测 鸿蒙OS加持,荣耀智慧屏评测:鸿蒙OS加持 面向未来的超智能电视...

原标题&#xff1a;荣耀智慧屏评测&#xff1a;鸿蒙OS加持 面向未来的超智能电视 来源&#xff1a;TechWeb.com.cn当华为选择在今年公布鸿蒙OS系统后&#xff0c;很多人都在期待它的庐山真面目。无论是以后非常时期不再受制于人&#xff0c;或是循序渐进将系统过渡给自家设备&a…

2021河南固高高考成绩查询,河南信阳最好的4所高中,前三所学霸如云,看看有没有你的母校?...

河南省信阳市处于豫之南&#xff0c;鄂之北。南边是连绵的群山&#xff0c;北边是广袤的平原。千里淮河&#xff0c;曲折盘旋&#xff0c;它的源头便是这里。都说信阳是一个神奇的地方&#xff0c;一点儿也不为过&#xff0c;狮河穿城而过&#xff0c;周围群山环抱&#xff0c;…

磁盘的磁道(Track)

写这篇文章&#xff0c;主要是为了解决长久以来的一个困惑。由此也可以看出偶以前确实不太聪明。 哈哈(虽然现在仍然还是) 以前见到的很多磁道的示意图都是这样的&#xff1a;注意标线的位置&#xff0c;“指向一条线”&#xff0c;我当时的理解好像是这条线就是磁道。还有的解…

centos 卸载_CentOS安装mysql

安装mysql第一步&#xff0c;查看是否安装&#xff1a;rpm -qa| grep mysql-server没有我们就开始安装&#xff0c;点击 这里&#xff0c;获取下载页面&#xff0c;按照图示选择合适的版本&#xff1a;第二步&#xff0c;进入/usr/local/soft/目录&#xff0c;在里面执行wget 下…

细数改善WPF应用程序性能的10大方法

WPF(Windows Presentation Foundation)应用程序在没有图形加速设备的机器上运行速度很慢是个公开的秘密&#xff0c;给用户的感觉是它太吃资源了&#xff0c;WPF程序的性能和硬件确实有很大的关系&#xff0c;越高档的机器性能越有优势。 程序性能改善不是一蹴而就的&#xff…

javaweb宿舍管理系统源码_宿舍信息管理系统展示

宿舍信息管理系统今天整理学习笔记的时候发现了自己当时学SSM框架的时候写了一个简单的Javaweb宿舍信息管理系统&#xff0c;虽然现在看来写的不是很好&#xff0c;但今日写此文章也算是纪念自己的第一个SSM小项目了&#xff0c;话不多说&#xff0c;直接开始。项目简介&#x…

Qt UDP的初步使用

为了使用Qt自带的Socket进行网络编程&#xff0c;先必须熟悉Socket编程的原理&#xff0c;另外还需对Qt一些基本类的操作比较熟悉。由于刚接触不久&#xff0c;所以还是以看人家的代码来学习。这次主要是学Qt下UDP的编程&#xff0c;且熟悉一些Qt下代码的编写流程&#xff0c;所…

下列哪一项不是计算机网络的典型应用,09级计算机信息网络试卷A

…………密…………封…………线…………内…………请…………不…………要…………答…………题…………河北工程大学11~12学年第二学期期末考试试卷A一、填空题(每空1分&#xff0c;共10分)1、在因特网中&#xff0c;远程登录Telnet系统采用的应用工作模式为____客户机&#…

hdu 4452

今天模拟赛的一个模拟题&#xff1b; 每次看到这种题就感觉很繁琐&#xff1b; 这次静下心来写写&#xff0c;感觉还不错&#xff01;就是很多错误&#xff0c;浪费了一点时间&#xff1b; 代码&#xff1a; 1 #include<cstdio>2 #include<cstring>3 using namespa…

openpyxl 绘制饼形图_好享学丨快速上手Pythonmatplotlib 箱线图绘制,学术人必备

好享学是高下制图推出的关于数据可视化经验分享栏目&#xff0c;我们将定期与您分享各界优秀人士的制图经验&#xff0c;一同学习。01. 引言箱线图(Boxplot) 是一种用作显示一组数据分散情况资料的统计图表&#xff0c;本期推文就如何使用matplotlib和seaborn 绘制出高度定制化…

揭开Socket编程的面纱

对TCP/IP、UDP、Socket编程这些词你不会很陌生吧&#xff1f;随着网络技术的发展&#xff0c;这些词充斥着我们的耳朵。那么我想问&#xff1a; 1. 什么是TCP/IP、UDP&#xff1f; 2. Socket在哪里呢&#xff1f; 3. Socket是什么呢&#xff1f; 4. 你会使用它们吗&#xff1f;…

socket中的函数遇见EINTR的处理

这几天&#xff0c;写服务器代码过程当中&#xff0c;遇见EINRT信号的问题&#xff0c;我是借鉴 《unp 》&#xff0c;采用continue或者goto again循环解决的。但是感觉这个还是很有必要记录一下。网络上查找到的信息很多。下面是我查找到的和EINTR有关的介绍&#xff1a;1 ht…