免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 922 | 回复: 0
打印 上一主题 下一主题

U-Boot的移植之(二)进阶篇:从源代码看系统启动过程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-10-18 00:37 |只看该作者 |倒序浏览

               
U-Boot Practically Porting Guide
Author: Aaron Wong

aaronwong@engineer.com
U-Boot的移植之(二)进阶篇:从源代码看系统启动过程
为什么要分析源代码?分析优秀的源代码本身就是一个学习的过程,也是进行深入研究的必经之路。不过在此我们的主要目的并非要研究U-boot或Bootloader技术本身,而仅仅是为了成功的并且恰当的将U-Boot移植到我们的开发板上。只有结合源代码了解了U-boot的系统引导过程,才能在移植和调试过程中保持清晰的思路,才能在碰到困难和问题时从根本上加以解决。
在动手分析之前,至少应该对U-Boot的源代码结构有基本的了解,很多参考书都有这方面的介绍,华清远见的《嵌入式Linux系统开发技术详解——基于ARM》的讲解就比较清晰。
本文以lubbock开发板为例,以系统启动的流程为线索进行纵向分析:后续的移植工作也将以此开发板为模板。Lubbock使用PXA255处理器。
首先要找到程序入口点。从board/lubbock/u-boot.lds可以发现,u-boot的程序入口为_start,在cpu/pxa/start.o当中。因此首先要分析start.S程序,U-Boot中所有的PXA系列的处理器都从这里开始执行第一条语句。
[color="#666600"].globl [color="#008080"]_start
[color="#008080"]_start: b reset
[color="#008080"]ldr pc, _undefined_instruction
[color="#008080"]ldr pc, _software_interrupt
[color="#008080"]ldr pc, _prefetch_abort
[color="#008080"]ldr pc, _data_abort
[color="#008080"]ldr pc, _not_used
[color="#008080"]ldr pc, _irq
[color="#008080"]ldr pc, _fiq
0x0地址开始是ARM异常向量表,学过ARM体系结构与编程的都明白,非常简单,不多废话。一上电的第一条指令是跳转到reset复位处理程序:
reset:
[color="#0000ff"]/* [color="#0000ff"]进入SVC[color="#0000ff"]模式 */
[color="#800080"]#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit [color="#0000ff"]/* we do sys-critical inits */
[color="#800080"]#endif
[color="#800080"]#ifndef CONFIG_SKIP_RELOCATE_UBOOT
[color="#000000"]relocate:
[color="#000000"]......
一般不要定义CONFIG_SKIP_LOWLEVEL_INIT,因此,接下来跳转到cpu_init_crit处开始执行:
cpu_init_crit:
[color="#0000ff"]/* [color="#0000ff"]屏蔽所有中断 */
[color="#0000ff"]/* 设置时钟源,关闭除FFUART,SRAM,SDRAM,FLASH以外的外设时钟 */
......
[color="#800080"]#ifdef CFG_CPUSPEED
ldr r0, CC_BASE [color="#0000ff"]/* [color="#0000ff"]时钟控制寄存器基址 */
ldr r1, cpuspeed
[color="#0000ff"]/* cpuspeed: .word CFG_CPUSPEED */
str r1, [r0, #CCCR]
mov r0, #2
mcr p14, 0, r0, c6, c0, 0
setspeed_done:
[color="#800080"]#endif [color="#0000ff"]/* CFG_CPUSPEED */
[color="#0000ff"]/* 跳转到lowlevel_init,这里ip即r12,用作暂存寄存器 */
[color="#0000ff"]mov ip, lr
[color="#000000"]bl lowlevel_init
[color="#000000"]mov lr, ip
[color="#000000"]/* Memory interfaces are working. Disable MMU and enable I-cache. */
[color="#000000"]ldr r0, =0x2001
[color="#000000"]......
[color="#000000"]/* [color="#0000ff"]关闭MMU[color="#0000ff"],使能I-Cache([color="#0000ff"]可选) */
[color="#000000"]mov pc, lr /* [color="#0000ff"]这里是从cpu_init_crit[color="#0000ff"]返回到relocate[color="#0000ff"]标号 */
可见,在cpu_init_crit中的主要工作是设置时钟,配置处理器主频(这时CPU的工作频率还没有改变),调用lowlevel_init函数进行底层初始化(包括调整处理器工作频率、系统总线频率、存储器时钟频率以及存储系统的初始化等工作),随后关闭MMU并使能I-Cache,再返回。
lowlevel_init函数在board/lubbock/lowlevel_init.S中定义,其流程都是按照PXA27X的开发手册来的,所以不再赘述。仅指出,其中的寄存器在include/asm-arm/arch-pxa/pxa-regs.h头文件中定义,寄存器初始化值在include/configs/lubbock.h中定义。另外,在后面的实际移植工作中,由于目标板XSBASE270使用的PXA270处理器,可使用adsvix开发板的lowlevel_init.S文件(lubbock中没有开启turbo模式)。
接着程序的执行线索进行分析。从cpu_init_crit返回后就开始relocate(重定位),即将U-boot从FLASH存储器搬运到SDRAM中TEXT_BASE开始的存储空间(TEXT_BASE在board/lubbock/config.mk中定义),并初始化堆栈(清零.bss段),以在SDRAM中开始进入到Bootloader stage 2的C程序入口。Relocate部分开始的代码如下:
[color="#0000ff"]/* 之前已定义的部分变量有:
[color="#0000ff"]_TEXT_BASE: .word TEXT_BASE
[color="#0000ff"]_armboot_start: .word _start
[color="#0000ff"]_bss_start: .word __bss_start
[color="#0000ff"]_bss_end: .word _end */
relocate: [color="#0000ff"]/* relocate U-Boot to RAM */
adr r0, _start [color="#0000ff"]/* r0
ldr r1, _TEXT_BASE [color="#0000ff"]/* test if we run from flash or RAM */
cmp r0, r1 [color="#0000ff"]/* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start [color="#0000ff"]/* [color="#0000ff"]读入_start[color="#0000ff"]到r2 */
ldr r3, _bss_start [color="#0000ff"]/* [color="#0000ff"]读入__bss_start[color="#0000ff"]到r3 */
sub r2, r3, r2 [color="#0000ff"]/* r2
add r2, r0, r2 [color="#0000ff"]/* r2
copy_loop:
ldmia r0!, {r3-r10} [color="#0000ff"]/* copy from source address [r0] */
stmia r1!, {r3-r10} [color="#0000ff"]/* copy to target address [r1] */
cmp r0, r2 [color="#0000ff"]/* until source end addreee [r2] */
ble copy_loop
[color="#0000ff"]/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE [color="#0000ff"]/* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN [color="#0000ff"]/* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE [color="#0000ff"]/* bdinfo */
[color="#800000"]#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
[color="#800000"]#endif
sub sp, r0, #12 [color="#0000ff"]/* leave 3 words for abort-stack */
clear_bss:
ldr r0, _bss_start [color="#0000ff"]/* find start of bss segment */
ldr r1, _bss_end [color="#0000ff"]/* stop here */
mov r2, #0x00000000 [color="#0000ff"]/* clear */
clbss_l:str r2, [r0] [color="#0000ff"]/* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_armboot
这是很经典的一段代码,相信学习凡是过ARM编程的,都分析过这段代码,所以也不再赘述。之所以列出这段代码,一是为了找到C程序入口start_armboot,二是为了给出U-Boot的一个存储器映射图:


这个图可以帮助我们更好地理解后续的C语言代码以及U-Boot对内存的分配与使用情况。
接下来进入到Bootloader Stage 2即C语言代码部分,入口是start_armboot,对应的源文件是lib_arm/board.c,这一文件对所有的ARM处理器都是通用的,因此在移植的时候不用修改。相关源代码如下:
DECLARE_GLOBAL_DATA_PTR;
[color="#0000ff"]/* 在include/asm-arm/global_data.h中定义的一个全局寄存器变量的声明:
[color="#0000ff"]* #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
[color="#0000ff"]* 用于存放全局数据结构体gd_t的地址。
[color="#0000ff"]*/
[color="#008000"]void start_armboot ([color="#008000"]void)
{
init_fnc_t **init_fnc_ptr;
[color="#008000"]char *s;
[color="#800080"]#ifndef CFG_NO_FLASH
ulong size;
[color="#800080"]#endif
[color="#800080"]#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
[color="#0000ff"]/* [color="#0000ff"]本次移植暂不配置VFD[color="#0000ff"]和LCD[color="#0000ff"],后面也将不考虑的部分略去 */
[color="#0000ff"]/* [color="#0000ff"]初始化全局数据结构体指针gd */
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - [color="#804c19"]sizeof(gd_t));
......[color="#0000ff"]/* memset[color="#0000ff"]在lib_generic/string.c[color="#0000ff"]中定义*/
memset ((void*)gd, 0, [color="#804c19"]sizeof (gd_t)); [color="#0000ff"]/*[color="#0000ff"]用0[color="#0000ff"]填充全局数据表*gd */
gd->bd = (bd_t*)((char*)gd - [color="#804c19"]sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t)); [color="#0000ff"]/*[color="#0000ff"]用0[color="#0000ff"]填充([color="#0000ff"]初始化) *gd->bd */
monitor_flash_len = _bss_start - _armboot_start;
[color="#804c19"]for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
[color="#804c19"]if ((*init_fnc_ptr)() != 0) {
hang (); [color="#0000ff"]/* [color="#0000ff"]打印错误信息并死锁 */
}
}
[color="#800080"]#ifndef CFG_NO_FLASH
[color="#0000ff"]/* configure available FLASH banks */
size = flash_init (); [color="#2300dc"]/* drivers/cfi_flash.c[color="#2300dc"]或自定义 */
display_flash_config (size);
[color="#800080"]#endif [color="#0000ff"]/* CFG_NO_FLASH */
[color="#0000ff"]/*armboot_start is defined in the board-specific linker script*/
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
......
[color="#0000ff"]/* initialize environment */
env_relocate ();
[color="#0000ff"]/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
[color="#0000ff"]/* MAC Address */
{
[color="#008000"]int i;
ulong reg;
[color="#008000"]char *s, *e;
[color="#008000"]char tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
[color="#804c19"]for (reg = 0; reg
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
[color="#804c19"]if (s)
s = (*e) ? e + 1 : e;
}
}
devices_init (); [color="#0000ff"]/* get the devices list going. */
.......
jumptable_init ();
console_init_r (); [color="#0000ff"]/* fully init console as a device */
enable_interrupts (); [color="#0000ff"]/* enable exceptions */
[color="#0000ff"]/* Perform network card initialisation if necessary */
[color="#800080"]#if defined(CONFIG_DRIVER_SMC91111)| |defined (CONFIG_DRIVER_LAN91C96)
[color="#804c19"]if (getenv ("ethaddr"))
smc_set_mac_addr(gd->bd->bi_enetaddr);
[color="#800080"]#endif [color="#0000ff"]/* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
[color="#0000ff"]/* Initialize from environment */
[color="#804c19"]if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
[color="#800080"]#if defined(CONFIG_CMD_NET)
[color="#804c19"]if ((s = getenv ("bootfile")) != NULL)
copy_filename (BootFile, s, sizeof (BootFile));
[color="#800080"]#endif
[color="#800080"]#ifdef BOARD_LATE_INIT
board_late_init ();
[color="#800080"]#endif
......
[color="#0000ff"]/*main_loop() can return to retry autoboot, if so just run it again.*/
[color="#804c19"]for (;;) {
main_loop ();
}
}
gd_t是全局数据表类型,在include/asm-arm/global_data.h中定义如下:
[color="#0000ff"]/*
[color="#0000ff"]Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t)
[color="#0000ff"]*/
[color="#008000"]typedef [color="#008000"]struct global_data {
bd_t *bd;
[color="#008000"]unsigned long flags;
[color="#008000"]unsigned long baudrate;
[color="#008000"]unsigned long have_console; [color="#0000ff"]/* serial_init() was called */
[color="#008000"]unsigned long reloc_off; [color="#0000ff"]/* Relocation Offset */
[color="#008000"]unsigned long env_addr; [color="#0000ff"]/* Address of Environment struct */
[color="#008000"]unsigned long env_valid; [color="#0000ff"]/*Checksum of Environment valid?*/
[color="#008000"]unsigned long fb_base; [color="#0000ff"]/* base address of frame buffer */
.......
[color="#008000"]void **jt; [color="#0000ff"]/* jump table */
} gd_t;
其中,bd_t在include/asm-arm/u-boot.h中定义如下:
[color="#008000"]typedef struct bd_info {
[color="#008000"]int bi_baudrate; [color="#0000ff"]/* serial console baudrate */
[color="#008000"]unsigned long bi_ip_addr; [color="#0000ff"]/* IP Address */
[color="#008000"]unsigned char bi_enetaddr[6]; [color="#0000ff"]/* Ethernet adress */
[color="#008000"]struct environment_s *bi_env;
ulong bi_arch_number; [color="#0000ff"]/* unique id for this board */
ulong bi_boot_params; [color="#0000ff"]/* where this board expects params*/
[color="#008000"]struct [color="#0000ff"]/* RAM configuration */
{
ulong start;
ulong size;
}bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;
jt是函数数组指针,随后将在jumptable_init()函数中初始化。
从lib_arm/board.c的源码不难分析出系统的启动流程:首先初始化全局数据表,然后顺序执行函数指针数组init_sequence中的一系列初始化函数——由其在本文件中的相关定义可得知初始化流程:
[color="#008000"]typedef int (init_fnc_t) ([color="#008000"]void);
init_fnc_t *init_sequence[] = {
cpu_init, [color="#0000ff"]/* basic cpu dependent setup -- [color="#2300dc"]cpu/pxa/cpu.c [color="#0000ff"]*/
board_init, [color="#0000ff"]/* basic board setup --[color="#2300dc"]board/lubbock/lubbock.c[color="#0000ff"] */
interrupt_init, [color="#0000ff"]/* set up exceptions -- [color="#2300dc"]cpu/pxa/interrupts.c[color="#0000ff"] */
env_init, [color="#0000ff"]/* initialize environment -- [color="#2300dc"]common/env_flash.c[color="#0000ff"] */
init_baudrate, [color="#0000ff"]/* initialze baudrate settings--[color="#2300dc"]lib_arm/board.c[color="#0000ff"] */
serial_init, [color="#0000ff"]/* serial communications setup--[color="#2300dc"]cpu/pxa/serial.c[color="#0000ff"] */
console_init_f, [color="#0000ff"]/* stage 1 init of console -- [color="#2300dc"]common/console.c [color="#0000ff"]*/
display_banner, [color="#0000ff"]/* say that we are here -- [color="#2300dc"]lib_arm/board.c[color="#0000ff"] */
[color="#800080"]#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, [color="#0000ff"]/* display board info */
[color="#800080"]#endif
dram_init, [color="#0000ff"]/* configure available RAM banks --board/lubbock/lubbock.c */
display_dram_config, [color="#0000ff"]/* [color="#2300dc"]lib_arm/board.c[color="#0000ff"] */
NULL,
};
在执行这个函数序列的过程中,任何一个函数异常返回都会导致u-boot“死锁”或说“挂起”在hang()函数的死循环当中。
若一切顺利,接下来就调用flash_init()函数初始化CFI FLASH(针对NOR型闪存而言),该函数在drivers/cfi_flash.c中定义,不过,只有在目标板头文件中”#define CFG_FLASH_CFI_DRIVER”之后该驱动才会被编译;在lubbock的u-boot实现当中,include/configs/lubbock.h中没有定义CFG_FLASH_CFI_DRIVER,而是在board/lubbock/ flash.c中实现了自己的FLASH驱动,包括flash_init()在内。在移植U-Boot时,可以根据实际情况选择使用U-Boot自带的FLASH驱动还是自己编写新的驱动。如果配置了NAND闪存,还会对其进行初始化;笔者的XSABSE270板没有焊接NAND FLASH,故对此不作讨论。
接下来调用env_relocate()函数初始化环境变量,该函数在common/env_common.c文件中定义。在同一文件中可以发现还定义了一个字符数组default_environment[],用于描述缺省的环境变量,这些都要在include/configs/lubbock.h头文件中进行设置,包括启动命令CONFIG_BOOTCOMMAND,波特率CONFIG_BAUDRATE,IP地址CONFIG_IPADDR等等。
然后是获取自设置的目标板的网络地址,包括IP地址和MAC地址。
再然后是调用common/devices.c中定义的devices_init()函数来创建设备列表,并初始化相应的设备,主要是”stdin”,”stdout”,”stderr”以及自定义的设备如I2C,LCD等。这些相关代码是与平台无关的,因此从移植的角度考虑,不必作细致的研究与分析。
接着调用common/exports.c中定义的jumptable_init()函数,初始化全局数据表中的跳转表gd->jt,跳转表是一个函数指针数组,定义了u-boot中基本的常用的函数库;而gd->jt是这个函数指针数组的首指针。部分代码如下:
[color="#008000"]void jumptable_init ([color="#008000"]void) {
[color="#008000"]int i;
gd->jt = ([color="#008000"]void **) malloc (XF_MAX * [color="#804c19"]sizeof (void *));
[color="#804c19"]for (i = 0; i
gd->jt = ([color="#008000"]void *) dummy;
gd->jt[XF_get_version] = ([color="#008000"]void *) get_version;
gd->jt[XF_malloc] = ([color="#008000"]void *) malloc;
gd->jt[XF_free] = ([color="#008000"]void *) free;
gd->jt[XF_getenv] = ([color="#008000"]void *) getenv;
gd->jt[XF_setenv] = ([color="#008000"]void *) setenv;
......
}
上面的XF_get_version, XF_malloc, XF_free等在include/exports.h的枚举变量中定义,因此,实际上是作为”Label式整型序号”使用,即XF_get_version=1, XF_malloc=2, XF_free=3 ...,相关代码如下:
enum { [color="#0000ff"]/* include/exports.h */
[color="#800080"]#define EXPORT_FUNC(x) XF_ ## x ,
#include
[color="#800080"]#undef EXPORT_FUNC
XF_MAX
};
EXPORT_FUNC(get_version)
EXPORT_FUNC(getc)
EXPORT_FUNC(tstc)
EXPORT_FUNC(putc)
EXPORT_FUNC(puts)
EXPORT_FUNC(printf)
......... [color="#0000ff"]/* include/_exports.h */
由于这些也是平台无关的代码,因此在移植过程中也不必深究。
然后是调用common/console.c中定义的函数console_init_r()初始化串口控制台,这同样是平台无关的代码,所以不必关心。
这时U-Boot的基本功能已经初始化完毕,便可开中断,并进行附加功能的配置与初始化,包括网卡驱动配置,目标板使用LAN91C1111网卡,对应SMC91111网卡驱动,可以根据需要配置其他的网卡驱动如CS8900等,这些都在include/configs/lubbock.h中定义。
然后是调用board/lubbock/lubbock.c中定义的board_late_init()函数进行板级的后期初始化,实际上是配置stdout和stderr的硬件设备。相关源代码如下:
[color="#008000"]int board_late_init([color="#008000"]void)
{
setenv("stdout", "serial");
setenv("stderr", "serial");
[color="#804c19"]return 0;
}
最后需要注意的一个很重要的文件是lib_arm/armlinux.c,它实现的功能包括设置内核启动参数,并负责将这些参数传递给内核,最后跳转到Linux内核入口函数,将控制权交给内核。
具体传递哪些参数,是通过在include/configs/lubbock.c中指定条件编译选项来控制的,对应于lib_arm/armlinux.c中的部分源代码形式如下:
[color="#800080"]#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
[color="#800080"]defined (CONFIG_CMDLINE_TAG) || \
[color="#800080"]defined (CONFIG_INITRD_TAG) || \
[color="#800080"]defined (CONFIG_SERIAL_TAG) || \
[color="#800080"]defined (CONFIG_REVISION_TAG)
[color="#008000"]static void setup_start_tag (bd_t *bd);
[color="#800080"]# ifdef CONFIG_SETUP_MEMORY_TAGS
[color="#008000"]static void setup_memory_tags (bd_t *bd);
[color="#800080"]# endif
[color="#008000"]static void setup_commandline_tag (bd_t *bd, char *commandline);
[color="#800080"]# ifdef CONFIG_INITRD_TAG
[color="#008000"]static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
ulong initrd_end);
[color="#800080"]# endif
[color="#008000"]static void setup_end_tag (bd_t *bd);
[color="#008000"]static struct tag *params;
[color="#800080"]#endif
[color="#000000"]......
[color="#000000"]void do_bootm_linux (cmd_tbl_t *cmdtp, [color="#008000"]int flag,[color="#008000"] int argc, [color="#008000"]char *argv[],
[color="#000000"]ulong addr, ulong *len_ptr, int verify)
[color="#000000"]{
[color="#000000"]......
[color="#000000"]void (*theKernel)([color="#008000"]int zero, [color="#008000"]int arch, uint params);
[color="#000000"]......
[color="#800080"]#ifdef CONFIG_CMDLINE_TAG
[color="#000000"]char *commandline = getenv ("bootargs");
[color="#800080"]#endif
[color="#000000"]theKernel = (void (*)([color="#008000"]int, [color="#008000"]int, uint))ntohl(hdr->ih_ep);
[color="#000000"]......
[color="#000000"]theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
[color="#000000"]}
关于这个参数列表中各个参数的定义及含义,以及参数列表的初始化过程,可以参考
Booting ARM Linux
一文。内核是如何找到这个参数列表在内存中的位置,以接收这些参数的呢?实际上,参数列表(tag list)在内存中的起始地址会保存在通用寄存器R2中,并传递给内核。而按照习惯或说惯例,通常tag list的首地址(物理地址)会设置为RAM起始地址+ 0x100偏移量,因此R2的值实际上是确定不变的。另外,还要正确设置R0和R1的值,在呼叫内核时,R0的值应为0,R1中则应保存机器类型(machine type)编号。R0,R1和R2都会作为参数传递给内核。
在上面的代码中,定义了一个函数指针theKernel,通过倒数第二条语句将内核入口地址赋给theKernel([color="#000000"]hdr[color="#000000"]是include/image.h[color="#000000"]中定义的一个image_header[color="#000000"]结构体类型的数据,hdr->ih_ep[color="#000000"]中保存了内核入口地址,ntohl[color="#000000"]的功能是字节顺序的大小端转换,相关代码可以参考tools/mkimage.c),最后,根据APCS规则,将[color="#000000"]0, bd->bi_arch_number, bd->bi_boot_params [color="#000000"]依次作为参数通过R0[color="#000000"],R1[color="#000000"]和R2[color="#000000"]传递给theKernel[color="#000000"]函数,并进入内核启动部分。
至此,我们已经从源代码入手简要分析了U-Boot的启动流程,在这个过程中,我们对前一篇文章“添加新的目标板定义”也有了更进一步的理解和认识:为什么要添加这些文件;哪些文件是平台相关的并且必须要根据平台特性进行修改的;哪些文件是平台无关的,是不需要修改的,只需在头文件中作适当配置即可。
下一节,我们将给出移植U-Boot到XSBASE270开发板的实例。
[Track]http://blog.chinaunix.net/u/26710/showart.php?id=402757
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/26710/showart_402757.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP