hello world.
分类: 嵌入式
2013-05-28 12:03:34
原文地址:AM335x SPL (四) 作者:Peter_Lee_CN
board_init_f
【入口函数】start.s (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S)
/*
Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI
compliance */
ldr r0,=0x00000000
bl board_init_f
设置栈指针,跳转到board_init_f
内部RAM分配如下:
1KB 0x402F0000 à (保护) 0x402F03FFà |
0x402F0400 à SPL (109KB) 0x4030B7FFà |
SP 0x4030B800à (10KB) 0x4030DFFFà |
RBL 0x4030E000à (8KB) 0x4030FFFFà |
board_init_f (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\Spl.c)
void board_init_f(ulong dummy)
{
/*
* We call relocate_code() with relocation target same as the
* CONFIG_SYS_SPL_TEXT_BASE. This will result in relocation getting
* skipped. Instead, only .bss initialization will happen. That's
* all we need
*/
debug(">>board_init_f()\n");
relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
}
代码重定位 relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
其中3个变量分别对应r0,r1,r2:
r0 : CONFIG_SPL_STACK = 0x4030B7FC
r1 : &gdata
r2 : CONFIG_SPL_TEXT_BASE = 0x402F0400
relocate_code (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S)
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */
beq clear_bss /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _image_copy_end_ofs
add r2, r0, r3 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r9-r10} /* copy from source address [r0] */
stmia r1!, {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
#ifndef CONFIG_SPL_BUILD
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* r0 <- Text base */
sub r9, r6, r0 /* r9 <- relocation offset */
ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
add r10, r10, r0 /* r10 <- sym table in FLASH */
ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
add r0, r0, r9 /* r0 <- location to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
cmp r7, #2 /* absolute fixup? */
beq fixabs
/* ignore unknown type of fixup */
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4] /* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
b clear_bss
_rel_dyn_start_ofs:
.word __rel_dyn_start - _start
_rel_dyn_end_ofs:
.word __rel_dyn_end - _start
_dynsym_start_ofs:
.word __dynsym_start - _start
#endif /* #ifndef CONFIG_SPL_BUILD */
board_init_r
【入口函数】start.s (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S)
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
jump_2_ram:
/*
* If I-cache is enabled invalidate it
*/
#ifndef CONFIG_SYS_ICACHE_OFF
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
#endif
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
add lr, lr, r9
/* setup parameters for board_init_r */
mov r0, r5 /* gd_t */
mov r1, r6 /* dest_addr */
/* jump to it ... */
mov pc, lr
_board_init_r_ofs:
.word board_init_r - _start
跳转到内部RAM执行board_init_r
board_init_r (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\Spl.c)
void board_init_r(gd_t *id, ulong dummy)
{
u32 boot_device;
debug(">>spl:board_init_r()\n");
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
CONFIG_SYS_SPL_MALLOC_SIZE);
timer_init();
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#ifdef CONFIG_SPL_BOARD_INIT //宏在Am335x_evm.h中打开
spl_board_init();
#endif
boot_device = omap_boot_device();
debug("boot device - %d\n", boot_device);
switch (boot_device) {
#ifdef CONFIG_SPL_MMC_SUPPORT
case BOOT_DEVICE_MMC1:
case BOOT_DEVICE_MMC2:
spl_mmc_load_image();
break;
#endif
#ifdef CONFIG_SPL_NAND_SUPPORT
case BOOT_DEVICE_NAND:
spl_nand_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:
spi_boot();
break;
#endif
#ifdef CONFIG_SPL_ETH_SUPPORT
case BOOT_DEVICE_CPGMAC:
spl_eth_load_image();
break;
#endif
default:
printf("SPL: Un-supported Boot Device - %d!!!\n", boot_device);
hang();
break;
}
switch (spl_image.os) {
case IH_OS_U_BOOT:
debug("Jumping to U-Boot\n");
jump_to_image_no_args();
break;
default:
puts("Unsupported OS image.. Jumping nevertheless..\n");
jump_to_image_no_args();
}
}
board_init_r 流程
à mem_malloc_init //初始化内存,设为0,0x80208000开始,大小1MB
à timer_init(); //定时器初始化,使用timer2,外部时钟源24MHz
à i2c_init //i2c初始化,速度为标准速度100000,从设备
à spl_board_init(); //spl板级初始化
à boot_device = omap_boot_device(); //获取启动模式
à switch (boot_device)
à spl_mmc_load_image(); ? //mmc载入镜像
à spl_nand_load_image(); //nand载入镜像
à spl_ymodem_load_image(); //ymode载入镜像
à spi_boot(); //spi载入镜像
à spl_eth_load_image(); //以太网载入镜像
à hang(); //挂起
à jump_to_image_no_args(); //跳转到uboot的入口地址entry_point执行
spl_board_init(); (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 */
board_init(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
if (!strncmp("A335BONE", header.name, 8)) {
/* BeagleBone PMIC Code */
if (i2c_probe(TPS65217_CHIP_PM))
return;
if (tps65217_reg_read(STATUS, &pmic_status_reg))
return;
/* Increase USB current limit to 1300mA */
if (tps65217_reg_write(PROT_LEVEL_NONE, POWER_PATH,
USB_INPUT_CUR_LIMIT_1300MA,
USB_INPUT_CUR_LIMIT_MASK))
printf("tps65217_reg_write failure\n");
/* Only perform PMIC configurations if board rev > A1 */
if (!strncmp(header.version, "00A1", 4))
return;
/* Set DCDC2 (MPU) voltage to 1.275V */
if (tps65217_voltage_update(DEFDCDC2,
DCDC_VOLT_SEL_1275MV)) {
printf("tps65217_voltage_update failure\n");
return;
}
/* Set LDO3, LDO4 output voltage to 3.3V */
if (tps65217_reg_write(PROT_LEVEL_2, DEFLS1,
LDO_VOLTAGE_OUT_3_3, LDO_MASK))
printf("tps65217_reg_write failure\n");
if (tps65217_reg_write(PROT_LEVEL_2, DEFLS2,
LDO_VOLTAGE_OUT_3_3, LDO_MASK))
printf("tps65217_reg_write failure\n");
if (!(pmic_status_reg & PWR_SRC_AC_BITMASK)) {
printf("No AC power, disabling frequency switch\n");
return;
}
/* Set MPU Frequency to 720MHz */
mpu_pll_config(MPUPLL_M_720);
} else {
uchar buf[4];
/*
* EVM PMIC code. All boards currently want an MPU voltage
* of 1.2625V and CORE voltage of 1.1375V to operate at
* 720MHz.
*/
if (i2c_probe(PMIC_CTRL_I2C_ADDR))
return;
/* VDD1/2 voltage selection register access by control i/f */
if (i2c_read(PMIC_CTRL_I2C_ADDR, PMIC_DEVCTRL_REG, 1, buf, 1))
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))
return;
if (!voltage_update(MPU, PMIC_OP_REG_SEL_1_2_6) &&
!voltage_update(CORE, PMIC_OP_REG_SEL_1_1_3))
/* Frequency switching for OPP 120 */
mpu_pll_config(MPUPLL_M_720);
}
}
#endif
spl_board_init();
à board_init(); //板级初始化
à PMIC //电源管理
à AM335x BeagleBone TPS65217
à mpu_pll_config(MPUPLL_M_720); //设MPU频率为720MHz
à 其他板卡 (TPS65910)
à mpu_pll_config(MPUPLL_M_720);
board_init(); (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)
int board_init(void)
{
/* Configure the i2c0 pin mux */
enable_i2c0_pin_mux();
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
if (read_eeprom())
goto err_out;
detect_daughter_board();
if (!strncmp("SKU#01", header.config, 6)) {
board_id = GP_BOARD;
detect_daughter_board_profile();
} else if (!strncmp("SKU#02", header.config, 6)) {
board_id = IA_BOARD;
detect_daughter_board_profile();
} else if (!strncmp("SKU#03", header.config, 6)) {
board_id = IPP_BOARD;
} else if (!strncmp("A335BONE", header.name, 8)) {
board_id = BONE_BOARD;
profile = 1; /* profile 0 is internally considered as 1 */
daughter_board_connected = 0;
} else if (!strncmp("A335X_SK", header.name, 8)) {
board_id = SK_BOARD;
profile = 1; /* profile 0 is internally considered as 1 */
daughter_board_connected = 0;
} else {
printf("Did not find a recognized configuration, "
"assuming General purpose EVM in Profile 0 with "
"Daughter board\n");
board_id = GP_BOARD;
profile = 1; /* profile 0 is internally considered as 1 */
daughter_board_connected = 1;
}
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected);
#ifndef CONFIG_SPL_BUILD
board_evm_init();
#endif
gpmc_init();
return 0;
err_out:
/*
* When we cannot use the EEPROM to determine what board we
* are we assume BeagleBone currently as we have not yet
* programmed the EEPROMs.
*/
board_id = BONE_BOARD;
profile = 1; /* profile 0 is internally considered as 1 */
daughter_board_connected = 1;
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected);
#ifndef CONFIG_SPL_BUILD
board_evm_init();
#endif
gpmc_init();
return 0;
}
board_init();
à设置、初始化I2C,读EEPROM
à有EEPROM
à根据读到的信息, 判断板卡型号GP_BOARD、IA_BOARD、IPP_BOARD(板卡有两部分组成)
BONE_BOARD、SK_BOARD(板卡单独一个整体)
à根据不同型号,配置相应的引脚
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected);
à gpmc_init(); //GPMC初始化,默认为8bit nand,起始地址和大小在Am335x_evm.h定义
à无EEPROM
à假设为有两部分组成的BONE_BOARD,并进行引脚配置
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected);
à gpmc_init();
configure_evm_pin_mux(board_id, header.version, profile, daughter_board_connected); //引脚配置
代码给出的引脚配置有以下几种,分别对应不同的评估板:
beaglebone_pin_mux,
general_purpose_evm_pin_mux,
ia_motor_control_evm_pin_mux,
ip_phone_evm_pin_mux,
low_cost_evm_pin_mux,
sk_evm_pin_mux,
以beaglebone、starterkit为例:
static struct evm_pin_mux beaglebone_pin_mux[] = {
{uart0_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
{i2c1_pin_mux, PROFILE_ALL & ~PROFILE_2 & ~PROFILE_4, DEV_ON_BASEBOARD},
#ifdef CONFIG_NAND
{nand_pin_mux, PROFILE_ALL & ~PROFILE_2 & ~PROFILE_3, DEV_ON_DGHTR_BRD},
#endif
#ifndef CONFIG_NO_ETH
{mii1_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#endif
#ifdef CONFIG_MMC
{mmc0_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
{mmc1_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#endif
#ifdef CONFIG_SPI
{spi0_pin_mux, PROFILE_2, DEV_ON_DGHTR_BRD},
#endif
{0},
};
Startkit没有nand,只有mmc,有两个千兆网
static struct evm_pin_mux sk_evm_pin_mux[] = {
{uart0_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#ifdef CONFIG_MMC
{mmc0_sk_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#endif
#ifndef CONFIG_NO_ETH
{rgmii1_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
{rgmii2_pin_mux, PROFILE_ALL, DEV_ON_BASEBOARD},
#endif
{0},
};
jump_to_image_no_args();
跳转到uboot的入口地址entry_point执行,这个entry_point哪里来?是有u-boot.img头部信息提供。
至此,整个AM335x SPL代码全部分析完毕,主要还是这3个函数:
? cpu_init_crit //cpu级初始化
? board_init_f //代码重定位
? board_init_r //板级初始化,并执行最终u-boot