本文共 27690 字,大约阅读时间需要 92 分钟。
u-boot-1.1.6学习笔记 Vicegod 2008-5-28 |-- board -->平台依赖,存放电路板相关源文件的目录,例如:dave、smdk2410等 |-- cpu -->平台依赖,存放与具体CPU型号相关源文件的目录,例如:arm720t、arm920t、i386等 |-- lib_arm -----------------------------------------------------------------------------------------------------> |-- lib_i386 -->平台依赖,用于存放对相应体系结构通用的文件,主要用于实现相关平台通用的函数 |-- lib_m68k -->比如lib_arm : |-- lib_microblaze -->存放对ARM体系结构通用的文件,主要用于实现ARM平台通用的函数 |-- lib_ppc -------------------------------------------------------------------------------------------------------> |-- lib_generic -->通用,对所有体系结构通用的库函数的实现,比如vsprintf、string等函数的实现 |-- include -->通用,头文件和开发板配置文件,所有开发板的配置文件都在 include/configs目录下 |-- common -->通用,通用的多功能函数实现,比如U-BOOT的命令setenv、bootm、cp等函数的实现 |-- drivers -->通用,通用设备的驱动程序
|-- nand_spl -->通用,Nand Flash boot的程序 |-- rtc -->通用,实时时钟(RTC)的驱动程序 |-- examples -->应用例程,一些独立运行的应用程序的例子,例如helloworld |-- tools -->工具,存放制作S-Record或者U-boot格式的映像等工具,例如mkimage |--> cup_init_crit: | |--> cpu_init_crit: | _start: --> reset: | |--> reset: --> relocate: --> _start_armboot: --> Start_armboot() --> main_loop() ---| u-boot-1.1.6/cpu/xxx/Start.S _start: u-boot-1.1.6/cpu/xxx/Start.S reset: u-boot-1.1.6/cpu/xxx/Start.S cup_init_crit: u-boot-1.1.6/board/yyy/lowlevel_init.S lowlevel_init: u-boot-1.1.6/cpu/xxx/Start.S relocate: u-boot-1.1.6/cpu/xxx/Start.S _start_armboot: u-boot-1.1.6/lib_arm/board.c start_armboot() u-boot-1.1.6/common/main.c main_loop() 说明:xxx(板子上具体的cpu型号,如arm920t) 3、u-boot-1.1.6/cpu/xxx/start.S分析 /* 这段代码的主要作用是初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备
好正确的环境 */ #if defined(CONFIG_OMAP1610) #include <./configs/omap1510.h> #elif defined(CONFIG_OMAP730) #include <./configs/omap730.h> /************************************************************************* * Jump vector table as in table 3.1 in [1] *************************************************************************/ _start: /* 系统复位位置, 各个异常向量对应的跳转代码 */ ldr pc, _undefined_instruction /* 未定义的指令异常向量 */ ldr pc, _software_interrupt /* 软件中断异常向量 */ ldr pc, _prefetch_abort /* 预取指令操作异常向量 */
ldr pc, _data_abort /* 数据操作异常向量 */ ldr pc, _not_used /* 未使用 */ ldr pc, _irq /* 慢速中断异常向量 */ ldr pc, _fiq /* 快速中断异常向量 */ .word undefined_instruction /************************************************分析**************************************************** * 从中我们可以看出,ARM支持7种异常。问题是发生了异常后ARM是如何响应的呢? * 第一个复位异常很好理解,它放在0x0的位置,一上电就执行它,而且我们的程序总是从 * 复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。那么什么时候会执行
* 当一个异常出现以后,ARM会自动执行以下几个步骤: * (1) 把下一条指令的地址放到连接寄存器LR(通常是R14),这样就能够在处理异常返回时从正确的位置继续执行。 * (2) 将相应的CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中。从异常退出的时候,就可以由SPSR来恢复CPSR。 * (3) 根据异常类型,强制设置CPSR的运行模式位。 * (4) PC(程序计数器)被强制成相关异常向量处理函数地址,从而跳转到相应的异常处理程序中。 * 当异常处理完毕后,ARM会执行以下几步操作从异常返回: * (1) 将连接寄存器LR的值减去相应的偏移量后送到PC中 * (3) 若在进入异常处理时设置了中断禁止位,要在此清除 * ldr pc, _undefined_instruction ; 未定义的指令异常 0x4 * ldr pc, _software_interrupt ; 软件中断异常 0x8 * ldr pc, _prefetch_abort ; 预取指令 0xc * ldr pc, _data_abort ; 数据 0x10 * ldr pc, _not_used ; 未使用 0x14 * ldr pc, _irq ; 慢速中断异常 0x18 * ldr pc, _fiq ; 快速中断异常 0x1c * 这样理解这段代码就非常简单了。碰到异常时,PC会被强制设置为对应的异常向量,从而跳转到 * .balignl 16,0xdeadbeef, 将地址对齐到16的倍数,如果地址寄存器的值(PC)跳过4个字节才是16的倍数, * 则使用0xdeadbeef填充这4个字节,如果它跳过1、2、3个字节,则填充值不确定。如果地址寄存器的值(PC)
********************************************************************************************************/ /************************************************************************* * Startup Code (reset vector) * do important init only if we don't start from memory! * setup Memory and board specific bits prior to relocation. * relocate armboot to ram *************************************************************************/ /* These are defined in the board-specific linker script.*/ /* IRQ stack memory (calculated at run-time) */ /* IRQ stack memory (calculated at run-time) */ /*************************************************分析********************************************************** * 上面这段代码,主要保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者其它的使用。 * 还有一些变量的值是通过连接脚本得到的,比如TEXT_BASE位于/u-boot-1.1.6/board/xxx(开发板目录名称)/config.mk * 文件里。__bss_start、_end位于/u-boot-1.1.6/board/xxx(开发板目录名称)/u-boot.lds文件里,具体值是由编译器算出来的。 ***************************************************************************************************************/ /* the actual reset code*/ /* 系统的复位代码。系统一上电,就跳到这里运行 */ * set the cpu to SVC32 mode
mrs r0,cpsr /* 取得当前程序状态寄存器cpsr到r0 */ bic r0,r0,#0x1f /* 这里使用位清除指令,把中断全部清除,只置位模式控制位 为中断提供服务通常是 OS *设备驱动程序的责任,因此在 Boot Loader 的执行全过程中可以不必响应任何中断。 orr r0,r0,#0xd3 /* 计算为超级保护模式 */ msr cpsr,r0 /* 设置cpsr为超级保护模式 */ /***********************************************分析************************************************************* * 设置cpu运行在SVC32模式。ARM共有7种模式: * 用户模式(usr): arm处理器正常的程序执行状态 * 快速中断模式(fiq): 用于高速数据传输或通道处理 * 超级保护模式(svc): 操作系统使用的保护模式 * 数据访问终止模式(abt): 当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护 * 系统模式(sys): 运行具有特权的操作系统任务 * 未定义指令中止模式(und): 当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真 * 通过设置ARM的CPSR寄存器,让CPU运行在操作系统保护模式,为后面进行其它操作作好准备了。 ****************************************************************************************************************/ * we do sys-critical inits only at reboot, * not when booting from ram! #ifndef CONFIG_SKIP_LOWLEVEL_INIT /****************************************************************************** * BL为相对寻址,以程序计数器PC 的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址 * ARM 指令集中的4条跳转指令可以完成从当前指令向前或向后的32MB 的地址空间的跳转, * 用的是相对寻址,它们是:B、BL、BLX、BX *******************************************************************************/ #ifndef CONFIG_SKIP_RELOCATE_UBOOT /* 重定位Boot代码到RAM内存,将Boot代码从FLASH移到RAM中 */ relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ /************************************************************************** * 把_start的相对地址移到r0, 相对寻址以程序计数器PC 的当前值为基地址, * 指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。 * 它是与位置无关的,主要看Boot在哪里运行,也就是PC指针在哪里 (假设_start偏移量为0), * 例如这段代码在 0x02000000 (FLASH起始地址)运行,即此时PC=0x02000000,那么 adr r0, _start 得到 r0 = 0x02000000; * 如果在地址 0x81008000(Boot在RAM中加载地址)运行,即此时PC=0x81008000,那么r0就是 0x81008000 了。 * 此处要注意ldr与adr的区别,看下面的代码片段: * 0c008000 <_start-0x14>: * c008000: e59f000c ldr r0, [pc, #12] ; c008014 <_start> * c008004: e28f0008 add r0, pc, #8 ; 0x8 * c008008: e59f0008 ldr r0, [pc, #8] ; c008018 <_start+0x4> * c00800c: e1a00000 nop (mov r0,r0) * c008010: e1a0f00e mov pc, lr * c008014: e1a00000 nop (mov r0,r0) * 从内存地址 _start 的地方把值读入。执行这个后,r0 = 0xe1a00000 * 取得 _start 的地址到 r0,但是请看反编译的结果,它是与位置无关的。其实取得的是相对的位置。例如这段代码在 0x0c008000 运行, * 那么 adr r0, _start 得到 r0 = 0x0c008014;如果在地址 0 运行,就是 0x00000014 了。即当前PC值加上_start的偏移量。 * 这个取得标号 _start 的绝对地址。这个绝对地址是在 link 的时候确定的。看上去这只是一个指令,但是它要占用 2 个 32bit 的空间, * 一条是指令,另一条是 _start 的数据(因为在编译的时候不能确定 _start 的值,所以不能直接用 mov 指令来给 r0 赋一个 32bit 的常量, * 所以需要多出一个空间存放 _start 的真正数据,这个数据是在 link 的时候确定的,在这里就是 0x0c008014)。 * 因此可以看出,这个是绝对的寻址,不管这段代码在什么地方运行,它的结果都是 r0 = 0x0c008014 **************************************************************************/
ldr r1, _TEXT_BASE/* test if we run from flash or RAM */ /* 把_TEXT_BASE地址处的值TEXT_BASE,也就是BOOT在RAM中运行地址移到r1 */ cmp r0, r1 /* don't reloc during debug */ /* 比较两个地址是否相同,如果相同,就已经在RAM运行,否则就是FLASH中运行 */ /* 如果是在FLASH中运行, 则把FLASH中的Boot代码移到RAM中,然后再运行 */ ldr r2, _armboot_start /* 把_armboot_start地址处的值也就是_start绝对地址(也即在内存中的地址,这个绝对 * 地址是在 link 的时候确定的,如0x81008000)移到r2 */ ldr r3, _bss_start /* 把_bss_start地址处的值也就是__bss_start绝对地址(也即在内存中的地址,这个绝对 * 地址是在 link 的时候确定的)移到r3 */ sub r2, r3, r2 /* r2 <- size of armboot */ /* 计算引导代码大小并存到r2 */ add r2, r0, r2 /* r2 <- source end address */ /* 计算引导代码最后相对地址并存入r2 */ ldmia r0!, {r3-r10} /* copy from source address [r0] */ /* 从源地址[r0]读取32个字节到寄存器,并更新r0 */ stmia r1!, {r3-r10} /* copy to target address [r1] */ /* 拷贝寄存器r3-r10的32个字节值保存到 [r1]指明的地址,并更新r1的值 */ cmp r0, r2 /* until source end addreee [r2] */ /* 循环拷贝,直到把所有引导代码都移到内存 */ #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) sub sp, r0, #12 /* leave 3 words for abort-stack */ ldr r0, _bss_start /* find start of bss segment*/ /* 把_bss_start地址处存储的绝对地址移到r0 */ ldr r1, _bss_end /* stop here */ /* 把_bss_end地址处存储的绝对地址移到r1 */ mov r2, #0x00000000 /* clear */ str r2, [r0] /* clear loop... STR 指令用于从源寄存器中r2将一个32 位的字数据传送到存储器中[r0]*/ ble clbss_l /* 小于或等于跳转 */ ldr pc, _start_armboot /*********************************************************** * 已经准备好了堆栈,就可跳到C写的代码里了,也就是 * 跳到内存中的/u-boot-1.1.6/board.c --> start_armboot中运行了 * 把_start_armboot地址处的值也就是start_armboot绝对地址值移到pc ***********************************************************/ /************************************************************************* * CPU_init_critical registers * setup important registers *************************************************************************/ /************************************************************************** * 1、关闭 MMU和CPU 内部指令/数据 (I/D)cache。 ****************************************************************************/ mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ /****************************************************************************************************** * MCR 指令用于将ARM 处理器寄存器中的数据传送到协处理器寄存器中,格式为: * MCR 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2。 * 其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作, * 源寄存器为ARM 处理器的寄存器,目的寄存器1 和目的寄存器2 均为协处理器的寄存器。 ******************************************************************************************************/ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ / * disable MMU stuff and caches*/ mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ mcr p15, 0, r0, c1, c0, 0 / * Go setup Memory and board specific bits prior to relocation.*/ mov ip, lr /* perserve link reg across call */ bl lowlevel_init /* go setup pll,mux,memory */ /* 位于u-boot-1.1.6/board/xxx(开发板目录名称)/lowlevel_init.S */ mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ /* 从cpu_init_crit子函数返回 */ /************************************************************************* *************************************************************************/ * use bad_save_user_regs for abort/prefetch/undef/swi ... * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling .macro bad_save_user_regs @ carve out a frame on current user stack sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack @ get values for "aborted" pc and cpsr (into parm regs)
add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr mov r0, sp @ save current stack into r0 (param register) .macro irq_save_user_regs sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0-r12 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. stmdb r8, {sp, lr}^ @ Calling SP, LR str lr, [r8, #0] @ Save calling PC str r6, [r8, #4] @ Save CPSR str r0, [r8, #8] @ Save OLD_R0 .macro irq_restore_user_regs ldmia sp, {r0 - lr}^ @ Calling r0 - lr ldr lr, [sp, #S_PC] @ Get PC add sp, sp, #S_FRAME_SIZE subs pc, lr, #4 @ return & move spsr_svc into cpsr ldr r13, _armboot_start @ setup our mode stack sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack str lr, [r13] @ save caller lr in position 0 of saved stack mrs lr, spsr @ get the spsr str lr, [r13, #4] @ save spsr in position 1 of saved stack mov r13, #MODE_SVC @ prepare SVC-Mode msr spsr, r13 @ switch modes, make sure moves will execute mov lr, pc @ capture return pc movs pc, lr @ jump to next instruction & switch modes. .macro get_irq_stack @ setup IRQ stack .macro get_fiq_stack @ setup FIQ stack .align 5 /*‘.align 5’向后移动位置计数器直至32(2^5)的倍数(计数器的最低的5位为0)。如果地址已经是32倍数,则无需移动。*/ bl do_undefined_instruction /* someone ought to write a more effiction fiq_save_user_regs */ 加载内核映像和根文件系统映像,规划它们的内存占用布局: 这里包括两个方面:(1)内核映像所占用的内存范围;(2)根文件系统所占用的内存范围。在规划内存占用的布局时,主要考虑基地址和映像的大小两个
方面。 对于内核映像,一般将其拷贝到从(MEM_START+0x8000) 这个基地址开始的大约1MB大小的内存范围内(嵌入式 Linux 的内核一般都不操过 1MB)。
为什么要把从 MEM_START 到 MEM_START+0x8000 这段 32KB 大小的内存空出来呢?这是因为 Linux 内核要在这段内存中放置一些全局数据结
构,如:启动参数和内核页表等信息。而对于根文件系统映像,则一般将其拷贝到 MEM_START+0x0010,0000 开始的地方。如果用 Ramdisk 作为根文
件系统映像,则其解压后的大小一般是1MB。
应该说,在将内核映像和根文件系统映像拷贝到 RAM 空间中后,就可以准备启动 Linux 内核了。但是在调用内核之前,应该作一步准备工作,即:设
置 Linux 内核的启动参数。 Boot Loader 调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START+0x8000 地址处。在跳转时,下列条件要满足: R1=机器类型 ID;关于 Machine Type Number,可以参见 linux/arch/arm/tools/mach-types。 * (C) Copyright 2002-2006 * Wolfgang Denk, DENX Software Engineering, . * Sysgo Real-Time Solutions, GmbH <>
* See file CREDITS for list of people who contributed to this * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * To match the U-Boot user interface on ARM platforms to the U-Boot * standard (as on PPC platforms), some messages with debug character * are removed from the default U-Boot build. * Define DEBUG here if you want additional info as shown below * U-Boot code: 00F00000 -> 00F3C774 BSS: -> 00FC3274 #ifdef CONFIG_DRIVER_SMC91111 #include "../drivers/smc91111.h" #ifdef CONFIG_DRIVER_LAN91C96 #include "../drivers/lan91c96.h" #if (CONFIG_COMMANDS & CFG_CMD_NAND) #ifdef CONFIG_HAS_DATAFLASH extern int AT91F_DataflashInit(void); extern void dataflash_print_info(void); #ifndef CONFIG_IDENT_STRING #define CONFIG_IDENT_STRING "" const char version_string[] = U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"CONFIG_IDENT_STRING; #ifdef CONFIG_DRIVER_CS8900 extern void cs8900_get_enetaddr (uchar * addr); #ifdef CONFIG_DRIVER_RTL8019 extern void rtl8019_get_enetaddr (uchar * addr); * Begin and End of memory area for malloc(), and current "brk" static ulong mem_malloc_start = 0;
static ulong mem_malloc_end = 0; static ulong mem_malloc_brk = 0; void mem_malloc_init (ulong dest_addr) mem_malloc_start = dest_addr; mem_malloc_end = dest_addr + CFG_MALLOC_LEN; mem_malloc_brk = mem_malloc_start; memset ((void *) mem_malloc_start, 0, mem_malloc_end - mem_malloc_start); void *sbrk (ptrdiff_t increment) ulong old = mem_malloc_brk; ulong new = old + increment; if ((new < mem_malloc_start) || (new > mem_malloc_end)) { /************************************************************************ ************************************************************************ * Some of this code should be moved into the core functions, * but let's get it working (again) first... static int init_baudrate (void) char tmp[64]; /* long enough for environment variables */ int i = getenv_r ("baudrate", tmp, sizeof (tmp)); gd->bd->bi_baudrate = gd->baudrate = (i > 0) ? (int) simple_strtoul (tmp, NULL, 10) static int display_banner (void) printf ("\n\n%s\n\n", version_string); debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", _armboot_start, _bss_start, _bss_end); #ifdef CONFIG_MODEM_SUPPORT
debug ("Modem Support enabled\n"); debug ("IRQ Stack: %08lx\n", IRQ_STACK_START); debug ("FIQ Stack: %08lx\n", FIQ_STACK_START); * WARNING: this code looks "cleaner" than the PowerPC version, but * has the disadvantage that you either get nothing, or everything. * On PowerPC, you might see "DRAM: " before the system hangs - which * gives a simple yet clear indication which part of the * initialization if failing. static int display_dram_config (void) puts ("RAM Configuration:\n"); for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) { printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
print_size (gd->bd->bi_dram[i].size, "\n"); for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) { size += gd->bd->bi_dram[i].size; static void display_flash_config (ulong size) #endif /* CFG_NO_FLASH */ * Breathe some life into the board... * Initialize a serial port as console, and carry out some hardware * The first part of initialization is running from Flash memory; * its main purpose is to initialize the RAM so that we * can relocate the monitor code to RAM. * All attempts to come up with a "common" initialization sequence * that works for all boards and architectures failed: some of the * requirements are just _too_ different. To get rid of the resulting * mess of board dependent #ifdef'ed code we now make the whole * initialization sequence configurable to the user. * The requirements for any new initalization function is simple: it * receives a pointer to the "global data" structure as it's only * argument, and returns an integer return code, where 0 means * "continue" and != 0 means "fatal error, hang the system". typedef int (init_fnc_t) (void); int print_cpuinfo (void); /* test-only */ 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) */ #if defined(CONFIG_DISPLAY_BOARDINFO) checkboard, /* display board info */ dram_init, /* configure available RAM banks */ void start_armboot (void) init_fnc_t **init_fnc_ptr; #if defined(CONFIG_VFD) || defined(CONFIG_LCD) /* Pointer is writable since we allocated a register for it */ gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); memset ((void*)gd, 0, sizeof (gd_t)); gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); monitor_flash_len = _bss_start - _armboot_start; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { /* configure available FLASH banks */ display_flash_config (size);
#endif /* CFG_NO_FLASH */ * reserve memory for VFD display (always full pages) /* bss_end is defined in the board-specific linker script */ addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); size = vfd_setmem (addr); * reserve memory for LCD display (always full pages) /* bss_end is defined in the board-specific linker script */ addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); size = lcd_setmem (addr); /* armboot_start is defined in the board-specific linker script */ mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); #if (CONFIG_COMMANDS & CFG_CMD_NAND) nand_init(); /* go init the NAND */ #ifdef CONFIG_HAS_DATAFLASH /* initialize environment */ /* must do this after the framebuffer is allocated */ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); i = getenv_r ("ethaddr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; i = getenv_r ("eth1addr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; for (reg = 0; reg < 6; ++reg) { gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0; devices_init (); /* get the devices list going. */ #endif /* CONFIG_CMC_PU2 */ console_init_r (); /* fully init console as a device */ #if defined(CONFIG_MISC_INIT_R) /* miscellaneous platform dependent initialisations */ /* Perform network card initialisation if necessary */ #ifdef CONFIG_DRIVER_TI_EMAC extern void emac_set_mac_addr (const char *addr); if (getenv ("ethaddr")) { emac_set_mac_addr(gd->bd->bi_enetaddr); #ifdef CONFIG_DRIVER_CS8900 cs8900_get_enetaddr (gd->bd->bi_enetaddr); #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) if (getenv ("ethaddr")) { smc_set_mac_addr(gd->bd->bi_enetaddr); #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ /* Initialize from environment */ if ((s = getenv ("loadaddr")) != NULL) { load_addr = simple_strtoul (s, NULL, 16); #if (CONFIG_COMMANDS & CFG_CMD_NET) if ((s = getenv ("bootfile")) != NULL) { copy_filename (BootFile, s, sizeof (BootFile)); #if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_NET_MULTI) /* main_loop() can return to retry autoboot, if so just run it again. */ /* NOTREACHED - no way out of command loop except booting */ puts ("### ERROR ### Please RESET the board ###\n"); #ifdef CONFIG_MODEM_SUPPORT static inline void mdm_readline(char *buf, int bufsiz); /* called from main loop (common/main.c) */ extern void dbg(const char *fmt, ...); extern char console_buffer[]; extern void enable_putc(void); extern int hwflow_onoff(int); enable_putc(); /* enable serial_putc() */ init_str = getenv("mdm_flow_control"); if (init_str && (strcmp(init_str, "rts/cts") == 0)) sprintf(env_str, "mdm_init%d", i); if ((init_str = getenv(env_str)) != NULL) { mdm_readline(console_buffer, CFG_CBSIZE); dbg("ini%d: [%s]", i, console_buffer);
if ((strcmp(console_buffer, "OK") == 0) || (strcmp(console_buffer, "ERROR") == 0)) { dbg("ini%d: cmd done", i); } else /* in case we are originating call ... */ if (strncmp(console_buffer, "CONNECT", 7) == 0) { dbg("ini%d: connect", i); break; /* no init string - stop modem init */ /* final stage - wait for connect */ for(;i > 1;) { /* if 'i' > 1 - wait for connection mdm_readline(console_buffer, CFG_CBSIZE); dbg("ini_f: [%s]", console_buffer); if (strncmp(console_buffer, "CONNECT", 7) == 0) { /* 'inline' - We have to do it fast */ static inline void mdm_readline(char *buf, int bufsiz) return; /* sanity check */ #endif /* CONFIG_MODEM_SUPPORT */ 转载地址:http://qpbqi.baihongyu.com/