初始化e500核心,清除指令和数据cache,有效指令和数据cache,设置中断向量,禁止中断响应,禁止看门狗,只允许machine check中断,设置为
supervisor级别,无效指令和数据cache,设置HID0寄存器等,为系统创建一个干净可靠的初始环境。
MMU初步配置
从前面P2020上电流程可以看出,上电之后,MMU只配置了4k空间,在这4k空间内必须初步配置MMU,使MMU能够映射u-boot真实的有效地址空间。下面这段代码将TLB1的Entry0配置为4M空间。 lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
/* create a temp mapping in AS=1 to the 4M boot window */
lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
/* The 85xx has the default boot window 0xff800000 - 0xffffffff */ lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
mtspr MAS0,r6 mtspr MAS1,r7 mtspr MAS2,r8 mtspr MAS3,r9 isync msync tlbwe
经过以上配置,u-boot代码就可以使用TEXT_BASE定义的有效地址空间了。但是,这时的Local Bus Bank的配置还是默认值。后面的代码会重新修改MMU映射,将u-boot映射到LAW分配的空间里。 Dcache中分配空间做堆栈
程序跑到这里,就要进入第一个C函数了。C函数的运行至少需要栈空间,但这时,RAM还没有初始化,只能在Dcache中锁定一定的空间,用做C的栈空间。
switch_as函数在Dcache中锁定16k的空间。
下面的几行代码将堆栈指针指向刚刚分配好的Dcache空间。
/* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/ lis r1,CONFIG_SYS_INIT_RAM_ADDR@h ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
li r0,0
stwu r0,-4(r1)
stwu r0,-4(r1) /* Terminate call chain */ cpu_init_f函数
该函数是系统执行的第一个C语言的函数,主要是做一些CPU 寄存器的初始化,其中最重要的部分是初始化Local Access Windows的值、Local Bus上的片选BR,OR的值和配置MMU的LTB1、LTB0。这些值需要在/include/configs/P2020DS.h中配置好。
board_init_f函数
该函数为板级初始化的第一个函数,会对板子上很多硬件外设做初始化,其中最重要的为init_sequence数组,该数组里面包含了很多板级的硬件初始化函数,在board_init_f函数中会依次的调用该数组中的函数去初始化各个硬件,该数组如下:
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif
#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) probecpu, #endif
#if !defined(CONFIG_8xx_CPUCLK_DEFAULT)
get_clocks, /* get CPU and bus clocks (etc.) */
#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) / && !defined(CONFIG_TQM885D) adjust_sdram_tbs_8xx, #endif
init_timebase, #endif
#ifdef CONFIG_SYS_ALLOC_DPRAM #if !defined(CONFIG_CPM2) dpram_init, #endif #endif
#if defined(CONFIG_BOARD_POSTCLK_INIT) board_postclk_init, #endif
env_init,
#if defined(CONFIG_8xx_CPUCLK_DEFAULT)
get_clocks_866, /* get CPU and bus clocks according to the environment variable */
sdram_adjust_866, /* adjust sdram refresh rate according to the new clock */ init_timebase, #endif
init_baudrate, serial_init,
console_init_f, display_options,
#if defined(CONFIG_8260) prt_8260_rsr, prt_8260_clks,
#endif /* CONFIG_8260 */
#if defined(CONFIG_MPC83xx) prt_83xx_rsr, #endif
checkcpu,
#if defined(CONFIG_MPC5xxx) prt_mpc5xxx_clks,
#endif /* CONFIG_MPC5xxx */ #if defined(CONFIG_MPC8220) prt_mpc8220_clks, #endif
checkboard,
INIT_FUNC_WATCHDOG_INIT #if defined(CONFIG_MISC_INIT_F) misc_init_f, #endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) init_func_i2c, #endif
#if defined(CONFIG_HARD_SPI) init_func_spi, #endif
#ifdef CONFIG_POST post_init_f, #endif
INIT_FUNC_WATCHDOG_RESET init_func_ram,
#if defined(CONFIG_SYS_DRAM_TEST) testdram,
#endif /* CONFIG_SYS_DRAM_TEST */ INIT_FUNC_WATCHDOG_RESET
NULL, /* Terminate this list */ };
有阴影的部分在本系统内不采用。可以看到时钟,串口,控制台,内存等初始化函数的调用。
relocate_code函数
到目前为止,boot代码都是在Flash中运行,但是代码最终是要到RAM中运行的,在上面的board_init_f函数中已经将RAM初始化好了,具备了在RAM中运行程序的能力,现在relocate_code函数需要做两个事情: 1) 从Flash中拷贝u-boot的代码到RAM;
2) 记下现在执行代码的偏移,跳转到RAM中相应的位置执行。
board_init_r函数
该函数为板级初始化的第二阶段,主要是初始化PCI,PCIE,网口,Flash等设备,关闭看门狗,把前面借dcache做堆栈的空间解锁,还给cache。在一切设备都初始化好后,便会进main_loop的死循环中。