cubieboard boot过程

cubieboard boot过程A10的启动过程大概可分为5步:BootRom,SPL,Uboot,Kernel,RootFileSystem。本文只关注镜像的加载过程,分析RootRom->SPL->Uboot的启动流程。系统上电后,ARM处理器在复位时从地址0x000000开始执行指令,把板上ROM或Flash映射到这一地址。A10将启动设备选择程序固化在CPU内部的一个32KBROM中,默认的启动时序为SD

大家好,又见面了,我是你们的朋友全栈君。

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启动模式。
启动设备选择程序的流程图:
cubieboard boot过程
 
在选择启动设备后将加载并执行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 (Mar
10
2013
00
:
36
:
40)

DRAM
:
1024MB

SUNXI SD
/MMC
:
0

U
Boot
2012.
10

04277
g7aa9f04 (Mar
10
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 mmc
0
:
1
for fatload
*
*

Loading file
“uEnv.txt” from mmc device
0
:
1

Failed to mount ext2 filesystem…


*
* Bad ext2 partition
or disk
mmc
0
:
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 partition
or disk
mmc
0
:
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 mmc
0
:
1
for fatload
*
*

Loading file
“boot.scr” from mmc device
0
:
1

Failed to mount ext2 filesystem…


*
* Bad ext2 partition
or disk
mmc
0
:
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 partition
or disk
mmc
0
:
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 mmc
0
:
1
for 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位置开始。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163073.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • kl1083_奥什科什M1083

    kl1083_奥什科什M1083Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为 2 的正整数被称为 Windy 数。Windy 想知道,在 A 和 B 之间,包括 A 和 B,总共有多少个 Windy 数?输入格式共一行,包含两个整数 A 和 B。输出格式输出一个整数,表示答案。数据范围1≤A≤B≤2×109输入样例1:1 10输出样例1:9输入样例2:25 50输出样例2:20#include<bits/stdc++.h>using namespace std;

  • 对比自监督学习综述 – A Survey of Contrastive Self-Supervised Learning

    对比自监督学习综述 – A Survey of Contrastive Self-Supervised Learning本文介绍了最近流行的对比自监督学习。

  • 内积空间上的等积变换_内积和距离的关系

    内积空间上的等积变换_内积和距离的关系内积空间、三角不等式、模长、不变子空间、镜像变换

  • python 0o_python中0o1010是多少

    python 0o_python中0o1010是多少python0o1010是多少?它以0开头,满足八进制的要求,是个八进制的数,下面来了解一下整数的四种表现形式:对于整数:有四种表现形式二进制:0,1满2进1八进制:0-7满8进1,用0开头表示十进制:0-9满10进1十六进制:0-9,A-F满16进1,用0x表示位(bit):存储信息的最小单位,表示一个二进制数字。字节(Byte):一个字节由8位二进制数字组成(1Byte=8bit)…

  • Scrivener for Mac如何自定义快捷键

    Scrivener for Mac如何自定义快捷键Scrivenerformac是目前苹果osx平台上最优秀的写作软件,拥有简单而又独特的操作界面,提供了标注、概述、收藏保存、全屏幕编辑、快照等各种写作辅助功能,可以对文章进行大致的勾勒或者重组,并且支持用户使用关键词跟踪主题,动态联合多种场景到单个文本,从而辅助作者完成从作品构思、搜集资料、组织结构、增删修改到排版输出的整个写作流程,能够适用于博主、作家、专栏作者使用。在ScrivenerforMac中分配或更改键盘快捷键可能存在某些菜单项,您发现自己使用了很多没有键盘快捷键的菜单项,或者您

  • mysql不执行命令_linux mysql启动命令

    mysql不执行命令_linux mysql启动命令Linux下使用mysql命令需要配置好环境以及各种文件,下面由学习啦小编为大家整理了linux下mysql命令不能用的相关知识,希望对大家有帮助!linux的mysql命令没用解决方法1.重新安装mysql命令,方法步骤如下:一安装步骤从这里下载你需要的版本(注意选择你操作系统是64位的还是32位的):这里只介绍两种判断linux是64位还是32的方法:命令:file/bin/cat[roo…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号