AM335x bootloader :
1st stage:RBL (ROM)
2st stage:SPL (内部RAM:0x402f0400)
3st stage:U-Boot (一般外部DDR)
SPL是bootloader的第二部分,由RBL引导运行,主要目的就是引导U-Boot运行。
SPL也叫MLO,一般存放在SD或者Nand中。其中,在Nand中要求存放在从第一个block开始的4个block中,因为RBL会从第一个block开始查找SPL,如果第一个失败后,会从第二个block开始继续查找,直到第四个block查找完毕,因此,SPL必须放在Nand从第一个block开始的4个block中,SPL在Nand中的偏移地址分别为0x0, 0x20000, 0x40000 和 0x60000。U-Boot从第五个block开始存放,即0x80000。假设Nand的block size为128K,则分布图如下:
- +------------+-->0x00000000-> SPL start (SPL copy on 1st block)
- | |
- | |-->0x0001FFFF-> SPL end
- | |-->0x00020000-> SPL.backup1 start (SPL copy on 2nd block)
- | |
- | |-->0x0003FFFF-> SPL.backup1 end
- | |-->0x00040000-> SPL.backup2 start (SPL copy on 3rd block)
- | |
- | |-->0x0005FFFF-> SPL.backup2 end
- | |-->0x00060000-> SPL.backup3 start (SPL copy on 4th block)
- | |
- | |-->0x0007FFFF-> SPL.backup3 end
- | |-->0x00080000-> U-Boot start
- | |
- | |-->0x002BFFFF-> U-Boot end
- | |-->0x00260000-> ENV start
- | |
- | |
- | |-->0x0027FFFF-> ENV end
- | |-->0x00280000-> Linux Kernel start
- | |
- | |
- | |
- | |
- | |-->0x0077FFFF-> Linux Kernel end
- | |-->0x00780000-> File system start
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- +------------+-->0x10000000-> NAND end (Free end)
参考http://blog.mcuol.com/User/nidetech/Article/79007_1.htm
(二)
SPL代码分析:
分析SPL代码,首先要看一下SPL目录下的Makefile文件,在Makefile中:
CONFIG_SPL_BUILD := y
export CONFIG_SPL_BUILD
这个宏定义用于打开U-boot代码里有关SPL部分的分支.
另外,Makefile还交代了SPL涉及到的相关代码文件:
主要有 u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7
u-boot-2011.09-psp04.06.00.08\arch\arm\lib
u-boot-2011.09-psp04.06.00.08\drivers
等.
除了通过Makefile分析SPL涉及到的相关代码文件外,还可以简单的通过在编译SPL时,在make 后加上O=am335x来将所有的.o文件归类在一起,在am335x/spl目录下:
通过上面的图,可以很清楚的了解SPL在编译时涉及到U-Boot中的代码文件
# Linker Script
ifdef CONFIG_SPL_LDSCRIPT
# need to strip off double quotes
LDSCRIPT := $(addprefix $(SRCTREE)/,$(subst ",,$(CONFIG_SPL_LDSCRIPT)))
endif
该处指定了SPL的链接脚本文件
CONFIG_SPL_LDSCRIPT 在 u-boot-2011.09-psp04.06.00.08\include\configs\Am335x_evm.h中定义:
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
所以SPL的链接脚本是u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\u-boot-spl.lds
在u-boot-spl.lds中,空间分配如下:
MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
LENGTH = CONFIG_SPL_MAX_SIZE }
MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
其中,CONFIG_SPL_TEXT_BASE、CONFIG_SPL_MAX_SIZE、CONFIG_SPL_BSS_START_ADDR、CONFIG_SPL_BSS_MAX_SIZE都是在Am335x_evm.h定义:
#define CONFIG_SPL_TEXT_BASE 0x402F0400
#define CONFIG_SPL_MAX_SIZE (101 * 1024)
#define CONFIG_SPL_BSS_START_ADDR 0x80000000
#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KB */
因此,实际的空间分配如下:
MEMORY { .sram : ORIGIN = 0x402F0400, LENGTH = (101 * 1024) }
MEMORY { .sdram : ORIGIN = 0x80000000, LENGTH = 0x80000 }
SRAM从0x402F0400开始用于存放.TEXT段、.rodata段、.data段内容
SDRAM从0x80000000开始用于存放.bss段内容
(三)
由Makefile可知,SPL的入口在u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S中
SPL的功能无非是设置MPU的Clock、PLL,Power,DDR,Uart,Pin Mux,完成对U-Boot的引导的工作,所以SPL board port主要针对以上几点。
在start.S中:
cpu_init_crit
board_init_f
board_init_r
cpu_init_crit
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
其中,CONFIG_SKIP_LOWLEVEL_INIT 在am335x_evm.h中定义:
/* Since SPL did all of this for us, we don't need to do it twice. */
#ifndef CONFIG_SPL_BUILD
#define CONFIG_SKIP_LOWLEVEL_INIT
#endif
由此可知,cpu_init_crit 只在SPL中才进行编译,U-Boot中不编译,避免了同样的内容重复设置,比如DDR等。
cpu_init_crit
----> lowlevel_init (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\lowlevel_init.S)
----> s_init (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
----> 关看门狗
----> pll_init(); //PLL和时钟设置
----> rtc32k_enable(); //使能RTC
----> 串口设置
----> init_timer();
----> preloader_console_init();
----> I2C0初始化,读EEPROM
----> DDR设置(DDR2\DDR3)
pll_init(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
----> mpu_pll_config(MPUPLL_M_500); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
//设置MPU的频率为500MHz,可以修改
----> core_pll_config(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
//设置CORE频率为1GHz
----> per_pll_config(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
//设置外设频率为960MHz
----> interface_clocks_enable(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
//使能内部连接模块的时钟
----> power_domain_transition_enable(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
//使能模块电源
----> per_clocks_enable(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)
//使能外设模块的时钟
在u-boot-2011.09-psp04.06.00.08\arch\arm\include\asm\arch-ti81xx\Clocks_am335x.h中,定义了所有时钟频率:
/* Put the pll config values over here */
#define OSC 24 /* 外部晶振为24MHz */
/* MAIN PLL Fdll = 1 GHZ, */
#define MPUPLL_M_500 500 /* 125 * n */
#define MPUPLL_M_550 550 /* 125 * n */
#define MPUPLL_M_600 600 /* 125 * n */
#define MPUPLL_M_720 720 /* 125 * n */
#define MPUPLL_N 23 /* (n -1 ) */
#define MPUPLL_M2 1
/* Core PLL Fdll = 1 GHZ, */
#define COREPLL_M 1000 /* 125 * n */
#define COREPLL_N 23 /* (n -1 ) */
#define COREPLL_M4 10 /* CORE_CLKOUTM4 = 200 MHZ */
#define COREPLL_M5 8 /* CORE_CLKOUTM5 = 250 MHZ */
#define COREPLL_M6 4 /* CORE_CLKOUTM6 = 500 MHZ */
/*
* USB PHY clock is 960 MHZ. Since, this comes directly from Fdll, Fdll
* frequency needs to be set to 960 MHZ. Hence,
* For clkout = 192 MHZ, Fdll = 960 MHZ, divider values are given below
*/
#define PERPLL_M 960
#define PERPLL_N 23
#define PERPLL_M2 5
/* DDR Freq is 266 MHZ for now*/
/* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */
#define DDRPLL_M 266
#define DDRPLL_N 23
#define DDRPLL_M2 1
MPU PLL结构:
配置MPU PLL:
代码如下:
void mpu_pll_config(int mpupll_M)
{
u32 clkmode, clksel, div_m2;
clkmode = readl(CM_CLKMODE_DPLL_MPU);
clksel = readl(CM_CLKSEL_DPLL_MPU);
div_m2 = readl(CM_DIV_M2_DPLL_MPU);
/* Set the PLL to bypass Mode */
writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_MPU);
while(readl(CM_IDLEST_DPLL_MPU) != 0x00000100);
clksel = clksel & (~0x7ffff);
clksel = clksel | ((mpupll_M << 0x8) | MPUPLL_N);
writel(clksel, CM_CLKSEL_DPLL_MPU);
div_m2 = div_m2 & ~0x1f;
div_m2 = div_m2 | MPUPLL_M2;
writel(div_m2, CM_DIV_M2_DPLL_MPU);
clkmode = clkmode | 0x7;
writel(clkmode, CM_CLKMODE_DPLL_MPU);
while(readl(CM_IDLEST_DPLL_MPU) != 0x1);
}
Core PLL 结构:
配置Core PLL:
代码如下:
static void core_pll_config(void)
{
u32 clkmode, clksel, div_m4, div_m5, div_m6;
clkmode = readl(CM_CLKMODE_DPLL_CORE);
clksel = readl(CM_CLKSEL_DPLL_CORE);
div_m4 = readl(CM_DIV_M4_DPLL_CORE);
div_m5 = readl(CM_DIV_M5_DPLL_CORE);
div_m6 = readl(CM_DIV_M6_DPLL_CORE);
/* Set the PLL to bypass Mode */
writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_CORE);
while(readl(CM_IDLEST_DPLL_CORE) != 0x00000100);
clksel = clksel & (~0x7ffff);
clksel = clksel | ((COREPLL_M << 0x8) | COREPLL_N);
writel(clksel, CM_CLKSEL_DPLL_CORE);
div_m4 = div_m4 & ~0x1f;
div_m4 = div_m4 | COREPLL_M4;
writel(div_m4, CM_DIV_M4_DPLL_CORE);
div_m5 = div_m5 & ~0x1f;
div_m5 = div_m5 | COREPLL_M5;
writel(div_m5, CM_DIV_M5_DPLL_CORE);
div_m6 = div_m6 & ~0x1f;
div_m6 = div_m6 | COREPLL_M6;
writel(div_m6, CM_DIV_M6_DPLL_CORE);
clkmode = clkmode | 0x7;
writel(clkmode, CM_CLKMODE_DPLL_CORE);
while(readl(CM_IDLEST_DPLL_CORE) != 0x1);
}
Peripheral PLL 结构
配置Peripheral PLL:
代码如下:
static void per_pll_config(void)
{
u32 clkmode, clksel, div_m2;
clkmode = readl(CM_CLKMODE_DPLL_PER);
clksel = readl(CM_CLKSEL_DPLL_PER);
div_m2 = readl(CM_DIV_M2_DPLL_PER);
/* Set the PLL to bypass Mode */
writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_PER);
while(readl(CM_IDLEST_DPLL_PER) != 0x00000100);
clksel = clksel & (~0x7ffff);
clksel = clksel | ((PERPLL_M << 0x8) | PERPLL_N);
writel(clksel, CM_CLKSEL_DPLL_PER);
div_m2 = div_m2 & ~0x7f;
div_m2 = div_m2 | PERPLL_M2;
writel(div_m2, CM_DIV_M2_DPLL_PER);
clkmode = clkmode | 0x7;
writel(clkmode, CM_CLKMODE_DPLL_PER);
while(readl(CM_IDLEST_DPLL_PER) != 0x1);
}
串口设置(u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
设置所使用串口的基地址、复位串口、关闭 smart idle。
u32 uart_base = DEFAULT_UART_BASE; // 默认使用的串口是UART0,基地址为 0x44E0_9000
enable_uart0_pin_mux(); // 配置uart0相关引脚为 UART模式
同样可以设置为其他串口,比如IA Motor Control Board就是使用的UART3,只要修改上面两步就可以了
init_timer(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
这里初始化的是timer2,在之前 pll_init();----> per_clocks_enable(); 中使能的也是timer2,使用24MHz OSC
preloader_console_init(); (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\Spl.c)
主要是对串口波特率的设置,以及串口终端打印信息。BeagleBone板上使用的是USB转串口芯片,串口驱动drivers\serial\serial.c 、drivers\serial\ns16550.c
I2C0初始化,读EEPROM (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
i2c0接了一个eeprom ( CAT24C256W 256K *8 ),i2c读取eeprom的数据到 header 结构体,header 结构体原型为
struct am335x_baseboard_id {
unsigned int magic;
char name[8];
char version[4];
char serial[12];
char config[32];
char mac_addr[NO_OF_MAC_ADDR][ETH_ALEN];
};
BeagleBone开发板提供的eeprom信息如下:
enable_i2c0_pin_mux(); // 配置i2c0相关引脚为 I2C模式
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);//i2c初始化,速度为标准速度100000,从设备
if (read_eeprom()) {
printf("read_eeprom() failure. continuing with ddr3\n");
} //读eeprom到 header 结构体,会判断magic是否为上表中提供的0xEE3355AA
DDR设置(DDR2\DDR3) (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
u32 is_ddr3 = 0;
if (!strncmp("A335X_SK", header.name, 8)) {
is_ddr3 = 1;
/*
* EVM SK 1.2A and later use gpio0_7 to enable DDR3.
* This is safe enough to do on older revs.
*/
enable_gpio0_7_pin_mux();
gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en");
gpio_direction_output(GPIO_DDR_VTT_EN, 1);
//通过gpio0_7输出高电平来触发VTT稳压器,从而产生VTT_DDR电压
}
if(is_ddr3 == 1){
ddr_pll_config(303);
config_am335x_ddr3();
}
else {
ddr_pll_config(266);
config_am335x_ddr2();
}
在设置DDR之前,要先判断是DDR2(变量is_ddr3 = 0)还是DDR3(变量is_ddr3 = 1),TI推出的开发板目前只有A335X_StarterKit支持DDR3,其余的均是DDR2,包括BeagleBone
一开始默认为DDR2(设置is_ddr3 = 0),但是通过比对header.name是否为A335X_SK,来确定DDR3(设置is_ddr3 = 1)
根据不同的DDR来进行相应的DDR配置,主要有4个部分需要设置,如下:
DDR PLL 结构:
配置DDR PLL:
代码如下:
ddr_pll_config(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c);
//配置ddr的时钟频率,DDR2为266MHz,DDR3为303MHz
void ddr_pll_config(unsigned int ddrpll_M)
{
u32 clkmode, clksel, div_m2;
clkmode = readl(CM_CLKMODE_DPLL_DDR);
clksel = readl(CM_CLKSEL_DPLL_DDR);
div_m2 = readl(CM_DIV_M2_DPLL_DDR);
/* Set the PLL to bypass Mode */
clkmode = (clkmode & 0xfffffff8) | 0x00000004;
writel(clkmode, CM_CLKMODE_DPLL_DDR);
while ((readl(CM_IDLEST_DPLL_DDR) & 0x00000100) != 0x00000100);
clksel = clksel & (~0x7ffff);
clksel = clksel | ((ddrpll_M << 0x8) | DDRPLL_N);
writel(clksel, CM_CLKSEL_DPLL_DDR);
div_m2 = div_m2 & 0xFFFFFFE0;
div_m2 = div_m2 | DDRPLL_M2;
writel(div_m2, CM_DIV_M2_DPLL_DDR);
clkmode = (clkmode & 0xfffffff8) | 0x7;
writel(clkmode, CM_CLKMODE_DPLL_DDR);
while ((readl(CM_IDLEST_DPLL_DDR) & 0x00000001) != 0x1);
}
config_am335x_ddr2();
(四)
【入口函数】u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S)board_init_f
内部
1KB 0x402F0000à (保护) 0x402F03FFà |
0x402F0400 à SPL (109KB) 0x4030B7FFà |
SP 0x4030B800à (10KB) 0x4030DFFFà |
RBL 0x4030E000à (8KB) 0x4030FFFFà |
u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\Spl.c)void board_init_f(ulong dummy)
/*
* CONFIG_SYS_SPL_TEXT_BASE. This will result in relocation getting
* all we need
debug(">>board_init_f()\n");
}
relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
其中r0,r1,r2:r0 : CONFIG_SPL_STACK 0x4030B7FC
&gdata
CONFIG_SPL_TEXT_BASE
u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S)/*------------------------------------------------------------------------------*/
/*
*
* after relocating the monitor code.
*/
relocate_code:
mov r5, r1 /* save addr of gd */
stack_setup:
cmp r0, r6
beq clear_bss /* skip relocation */
ldr r3, _image_copy_end_ofs
ldmia r0!, {r9-r10} /* copy from source address [r0] */
cmp r0, r2 /* until source end address [r2] */
/*
*/
sub r9, r6, r0 /* r9 <- relocation offset */
add r10, r10, r0 /* r10 <- sym table in FLASH */
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
ldr r1, [r2, #4]
cmp r7, #23 /* relative fixup? */
cmp r7, #2 /* absolute fixup? */
/* ignore unknown type of fixup */
fixabs:
mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
ldr r1, [r1, #4] /* r1 <- symbol value */
b fixnext
/* relative fix: increase location by offset */
add r1, r1, r9
str r1, [r0]
cmp r2, r3
b clear_bss
.word __rel_dyn_start - _start
.word __rel_dyn_end - _start
.word __dynsym_start - _start
#endif /* #ifndef CONFIG_SPL_BUILD */
start.s (
* We are done. Do not return, instead branch to second part of board
*/
/*
*/
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c5, 4 @ ISB
ldr r0, _board_init_r_ofs
add lr, r0, r1
/* setup parameters for board_init_r */
mov r1, r6 /* dest_addr */
mov pc, lr
_board_init_r_ofs:
RAM执行board_init_r (
{
debug(">>spl:board_init_r()\n");
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
timer_init();
;
Am335x_evm.h中打开 spl_board_init();
debug("boot device - %d\n", boot_device);
#ifdef CONFIG_SPL_MMC_SUPPORT
case BOOT_DEVICE_MMC2:
break;
#ifdef CONFIG_SPL_NAND_SUPPORT
spl_nand_load_image();
#endif
case BOOT_DEVICE_UART:
break;
#ifdef CONFIG_SPL_SPI_SUPPORT
spi_boot();
#endif
case BOOT_DEVICE_CPGMAC:
break;
default:
hang();
}
switch (spl_image.os) {
debug("Jumping to U-Boot\n");
break;
puts("Unsupported OS image.. Jumping nevertheless..\n");
}
mem_malloc_init 0,1MB à //定时器初始化,使用24MHz i2c_init 100000,从设备 spl_board_init();//spl板级初始化 boot_device = omap_boot_device();
à spl_mmc_load_image(); ? //mmc载入镜像spl_nand_load_image();
à //ymode载入镜像spi_boot();
à //以太网载入镜像hang();
jump_to_image_no_args(); uboot的入口地址
u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)void spl_board_init(void)
uchar pmic_status_reg;
/* init board_id, configure muxes */
u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
/* BeagleBone PMIC Code */
return;
if (tps65217_reg_read(STATUS, &pmic_status_reg))
if (tps65217_reg_write(PROT_LEVEL_NONE, POWER_PATH,
USB_INPUT_CUR_LIMIT_MASK))
if (!strncmp(header.version, "00A1", 4))
if (tps65217_voltage_update(DEFDCDC2,
printf("tps65217_voltage_update failure\n");
}
/* Set LDO3, LDO4 output voltage to 3.3V */
LDO_VOLTAGE_OUT_3_3, LDO_MASK))
LDO_VOLTAGE_OUT_3_3, LDO_MASK))
printf("No AC power, disabling frequency switch\n");
}
/* Set MPU Frequency to 720MHz */
} else {
/*
* of 1.2625V and CORE voltage of 1.1375V to operate at
*/
return;
/* VDD1/2 voltage selection register access by control i/f */
return;
buf[0] |= PMIC_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C;
if (i2c_write(PMIC_CTRL_I2C_ADDR, PMIC_DEVCTRL_REG, 1, buf, 1))
!voltage_update(CORE, PMIC_OP_REG_SEL_1_1_3))
mpu_pll_config(MPUPLL_M_720);
}
à
PMIC
AM335x BeagleBone
mpu_pll_config(MPUPLL_M_720); MPU频率为
TPS65910) à
board_init(); (
{
enable_i2c0_pin_mux();
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
if (read_eeprom())
board_id = GP_BOARD;
} else if (!strncmp("SKU#02", header.config, 6)) {
detect_daughter_board_profile();
board_id = IPP_BOARD;
board_id = BONE_BOARD;
daughter_board_connected = 0;
board_id = SK_BOARD;
daughter_board_connected = 0;
printf("Did not find a recognized configuration, "
"Daughter board\n");
profile = 1; /* profile 0 is internally considered as 1 */
}
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected);
#ifndef CONFIG_SPL_BUILD
#endif
gpmc_init();
return 0;
err_out:
* When we cannot use the EEPROM to determine what board we
* programmed the EEPROMs.
board_id = BONE_BOARD;
daughter_board_connected = 1;
board_evm_init();
}
board_init();
I2C,读 à有
判断板卡型号IA_BOARD、
SK_BOARD(板卡单独一个整体)
à 8bit nand,起始地址和大小在
EEPROM à假设为有两部分组成的
à
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected);
代码给出的引脚配置有以下几种,分别对应不同的评估板:
general_purpose_evm_pin_mux,
ip_phone_evm_pin_mux,
sk_evm_pin_mux,
beaglebone、
static struct evm_pin_mux beaglebone_pin_mux[] = {
{i2c1_pin_mux, PROFILE_ALL & ~PROFILE_2 & ~PROFILE_4, DEV_ON_BASEBOARD},
{nand_pin_mux, PROFILE_ALL & ~PROFILE_2 & ~PROFILE_3, DEV_ON_DGHTR_BRD},
#ifndef CONFIG_NO_ETH
#endif
{mmc0_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#endif
{spi0_pin_mux, PROFILE_2, DEV_ON_DGHTR_BRD},
{0},
nand,只有
{uart0_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
{mmc0_sk_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
{rgmii1_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#endif
};
jump_to_image_no_args();
跳转到entry_point执行,这个u-boot.img头部信息提供。
至此,整个3个函数:cpu_init_crit //cpu级初始化board_init_f //代码重定位board_init_r //板级初始化,并执行最终
(BOOTLOADER) AM335x bootloader 分3部分: 1st stage:RBL (ROM) 2st stage:SPL (内部RAM:0x402f0400) 3st stage:U-Boot (一般外部DDR) 注:SPL的代码包含在U-Boot中,在编译U-Boot时会自动编译。 AM335x内部RAM大小为128KB(0x402f0000 - 0x4030ffff),其中底部8KB(0x4030e000 - 0x4030ffff)来作载入ROM code(RBL)用,另外,开始1KB(0x402f0000 - 0x402f0400)用作保护(该部分是无法进入的),因此只剩下109KB来存放U-Boot镜像,以及存放在DRAM初始化之前的整个栈(stack)。然而,实际上U-Boot要完成相应的功能所需要的代码是无法压缩到110KB以内的,所以必须分两步(two stages)。 注:如果从nand启动,所有镜像(image)都必须有头部信息(image header),image header长度为8 byte,包含loader address(Entry point)以及需要拷贝的image大小。