首页 技术 正文
技术 2022年11月10日
0 收藏 908 点赞 4,798 浏览 22251 个字

http://blog.chinaunix.net/uid-28458801-id-3486399.html

参考文件:

1,AM335x ARM Cortex-A8 Microprocessors (MPUs) Technical Reference Manual.pdf;

2,am3359.pdf;

1,am335x的cpu上电后,会跳到哪个地址去执行?

答:

芯片到uboot启动流程 :ROM → MLO(SPL)→ uboot.img

AM335x 中bootloader被分成了 3 个部分:

第一级 bootloader:引导加载程序,板子上电后会自动执行这些代码,如选择哪种方式启动(NAND,SDcard,UART。。。),然后跳转转到第二级 bootloader。这些代码应该是存放在 176KB 的 ROM 中。

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

第二级 bootloader:MLO(SPL),用以硬件初始化:关闭看门狗,关闭中断,设置 CPU 时钟频率、速度等操作。然后会跳转到第三级bootloader。MLO文件应该会被映射到 64 KB的 Internal SRAM 中。

转:AM335x启动流程(BootRom->MLO->Uboot)

第三级 bootloader:uboot.img,C代码的入口。

转:AM335x启动流程(BootRom->MLO->Uboot)

其中第一级 bootloader 是板子固化的,第二级和第三级是通过编译 uboot 所得的。

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

2,第二级 bootloader:MLO(SPL)做了哪些事情?

MLO(SPL)内存分布如下:

转:AM335x启动流程(BootRom->MLO->Uboot)

SPL内存重映射:

123456789101112131415161718192021222324252627282930313233343536 < PATH : /arch/arm/cpu/armv7/omap-common/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 } OUTPUT_FORMAT("elf32-littlearm""elf32-littlearm""elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{    .text      :    {    __start = .;      arch/arm/cpu/armv7/start.o    (.text)      *(.text*)    } >.sram     . = ALIGN(4);    .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram     . = ALIGN(4);    .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram    . = ALIGN(4);    __image_copy_end = .;    _end = .;     .bss :    {        . = ALIGN(4);        __bss_start = .;        *(.bss*)        . = ALIGN(4);        __bss_end__ = .;    } >.sdram}
1234567 <PATH : /include/configs/am335x_evm.h>#define CONFIG_SPL_TEXT_BASE        0x402F0400#define CONFIG_SPL_MAX_SIZE     (46 * 1024)#define CONFIG_SPL_STACK        LOW_LEVEL_SRAM_STACK #define CONFIG_SPL_BSS_START_ADDR   0x80000000#define CONFIG_SPL_BSS_MAX_SIZE     0x80000     /* 512 KB */ <span style="font-size:16px;color:#003399;"><strong></strong></span>

    @1@ 保存启动参数 bl    save_boot_params

1234567 <PATH : /arch/arm/cpu/armv7/start.S>/* * the actual reset code */ reset:    bl  save_boot_params
123456789101112131415161718192021222324 <PATH : /arch/arm/cpu/armv7/omap-common/lowlevel_init.S>.global save_boot_paramssave_boot_params:    /*     * See if the rom code passed pointer is valid:     * It is not valid if it is not in non-secure SRAM     * This may happen if you are booting with the help of     * debugger     */    ldr     r2, =NON_SECURE_SRAM_START    cmp r2, r0    bgt 1f    ldr r2, =NON_SECURE_SRAM_END    cmp r2, r0    blt 1f     /*     * store the boot params passed from rom code or saved     * and passed by SPL     */    cmp r0, #0    beq 1f    ldr r1, =boot_params    str r0, [r1]
12345678 /*《PATH: /arch/arm/include/asm/arch-ti81xx/omap.h》 * Non-secure SRAM Addresses * Non-secure RAM starts at 0x40300000 for GP devices. But we keep SRAM_BASE * at 0x40304000(EMU base) so that our code works for both EMU and GP */#define NON_SECURE_SRAM_START   0x40304000#define NON_SECURE_SRAM_END 0x4030E000#define LOW_LEVEL_SRAM_STACK    0x4030B7FC

问题:这些参数是保存在哪里的?大概有哪些参数?

答:

这些参数保存的内存地址为 64 KB 的 OCM RAM 中:

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

注:Dowloaded Image 区域:是用来保存 MLO(SPL) 文件的,其最大可达到 109 KB

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

    @a2@ 设置 CPU 为 SVC32 模式

12345678     <PATH : /arch/arm/cpu/armv7/start.S>               /*     set the cpu to SVC32 mode     */    mrs r0, cpsr    bic r0, r0, #0x1f    orr r0, r0, #0xd3    msr cpsr,r0

   CPSR:程序状态寄存器(current program status register)(当前程序状态寄存器),在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。
CPSR在用户级编程时用于存储条件码。

  SPSR:程序状态保存寄存器(saved program statusregister),每一种处理器模式下都有一个状态寄存器SPSR,SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常中断退出时,可以用SPSR来恢复CPSR。由于用户模式和系统模式不是异常中断模式,所以他没有SPSR。当用户在用户模式或系统模式访问SPSR,将产生不可预知的后果。

CPSR格式如下所示。SPSR和CPSR格式相同。
31 30 29 28 27 26 7 6 5 4 3 2 1 0
N Z C V Q DNM(RAZ) I F T M4 M3 M2 M1 M0

详解:http://blog.chinaunix.net/uid-28458801-id-3487199.html

    @a3@ CPU的初始化

12345 《PATH : /arch/arm/cpu/armv7/start.S》    /* the mask ROM code should have PLL and others stable */#ifndef CONFIG_SKIP_LOWLEVEL_INIT    bl  cpu_init_crit#endif
123456789101112131415161718 <PATH : /arch/arm/cpu/armv7/omap-common/lowlevel_init.S>.globl lowlevel_initlowlevel_init:    /*     * Setup a temporary stack     */    ldr sp, =LOW_LEVEL_SRAM_STACK     /*     * Save the old lr(passed in ip) and the current lr to stack     */    push    {ip, lr}     /*     * go setup pll, mux, memory     */    bl  s_init    pop {ip, pc}

问题:CPU的初始化有哪些内容?

答:

            @b1@ 首先要设置堆栈区,因为将会调用 C函数来实现CPU的初始化

问题:这个堆栈在什么位置,其内存大小是多少?

12 《PATH :/arch/arm/include/asm/arch-ti81xx/omap.h》#define LOW_LEVEL_SRAM_STACK    0x4030B7FC<strong></strong>

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

 

            @b2@ 执行 s_init() 函数,实现 CPU 的初始化

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 <PATH : /board/ti/am335x/evm.c>/* * early system init of muxing and clocks. */void s_init(void){    /* Can be removed as A8 comes up with L2 enabled */    l2_cache_enable();     /* WDT1 is already running when the bootloader gets control     * Disable it to avoid "random" resets     */    __raw_writel(0xAAAA, WDT_WSPR);    while(__raw_readl(WDT_WWPS) != 0x0);    __raw_writel(0x5555, WDT_WSPR);    while(__raw_readl(WDT_WWPS) != 0x0); #ifdef CONFIG_SPL_BUILD    /* Setup the PLLs and the clocks for the peripherals */    pll_init();     /* Enable RTC32K clock */    rtc32k_enable();     /* UART softreset */    u32 regVal;    u32 uart_base = DEFAULT_UART_BASE;     enable_uart0_pin_mux();    /* IA Motor Control Board has default console on UART3*/    /* XXX: This is before we've probed / set board_id */    if (board_id == IA_BOARD) {        uart_base = UART3_BASE;    }     regVal = __raw_readl(uart_base + UART_SYSCFG_OFFSET);    regVal |= UART_RESET;    __raw_writel(regVal, (uart_base + UART_SYSCFG_OFFSET) );    while ((__raw_readl(uart_base + UART_SYSSTS_OFFSET) &            UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK);     /* Disable smart idle */    regVal = __raw_readl((uart_base + UART_SYSCFG_OFFSET));    regVal |= UART_SMART_IDLE_EN;    __raw_writel(regVal, (uart_base + UART_SYSCFG_OFFSET));     /* Initialize the Timer */    init_timer();     preloader_console_init();     printf("\nlocation /board/ti/am335x\n");        //@@/*@@*///  led();/*@@*/         config_am335x_ddr(); #endif}

                    @c1@ 使能第二级缓冲区

12345678910     /* Can be removed as A8 comes up with L2 enabled */    l2_cache_enable(); <PATH : /arch/arm/cpu/armv7/ti81xx/cache.S>l2_cache_enable:    push    {r0, r1, r2, lr}    mrc 15, 0, r3, cr1, cr0, 1    orr r3, r3, #2    mcr 15, 0, r3, cr1, cr0, 1    pop {r1, r2, r3, pc}

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c2@ 关闭看门狗(WDT)

1234567 /* WDT1 is already running when the bootloader gets control * Disable it to avoid "random" resets */__raw_writel(0xAAAA, WDT_WSPR);while(__raw_readl(WDT_WWPS) != 0x0);__raw_writel(0x5555, WDT_WSPR);while(__raw_readl(WDT_WWPS) != 0x0);
1234567891011 <PATH : /arch/arm/include/asm/arch-ti81xx/cpu.h>#define WDT_WSPR    (WDT_BASE + 0x048)  <PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h>/* Watchdog Timer */#ifdef CONFIG_AM335X#define WDT_BASE            0x44E35000#else#define WDT_BASE            0x480C2000#endif

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c3@ 给外设设置好 PLL 和 时钟频率等

123456789101112131415161718192021     /* Setup the PLLs and the clocks for the peripherals */    pll_init();  <PATH : /board/ti/am335x/pll.c>/* * Configure the PLL/PRCM for necessary peripherals */void pll_init(){    mpu_pll_config(MPUPLL_M_500);    core_pll_config();    per_pll_config();    ddr_pll_config();    /* Enable the required interconnect clocks */    interface_clocks_enable();    /* Enable power domain transition */    power_domain_transition_enable();    /* Enable the required peripherals */    per_clocks_enable();}

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c4@ 使能 32-KHz 频率的实时时钟

1234567891011121314151617181920212223     /* Enable RTC32K clock */    rtc32k_enable();  《PATH : /board/ti/am335x/evm.c》static void rtc32k_enable(void){    /* Unlock the rtc's registers */    __raw_writel(0x83e70b13, (AM335X_RTC_BASE + RTC_KICK0_REG));    __raw_writel(0x95a4f1e0, (AM335X_RTC_BASE + RTC_KICK1_REG));     /* Enable the RTC 32K OSC */    __raw_writel(0x48, (AM335X_RTC_BASE + RTC_OSC_REG));} <PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h>/* RTC base address */#define AM335X_RTC_BASE            0x44E3E000 <PATH : /board/ti/am335x/evm.c>#define RTC_KICK0_REG        0x6c#define RTC_KICK1_REG        0x70#define RTC_OSC_REG        0x54

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c5@ 使能UART0

12345678910111213141516171819202122232425262728293031323334     /* UART softreset */    u32 regVal;    u32 uart_base = DEFAULT_UART_BASE;     enable_uart0_pin_mux();    /* IA Motor Control Board has default console on UART3*/    /* XXX: This is before we've probed / set board_id */    if (board_id == IA_BOARD) {        uart_base = UART3_BASE;    }     regVal = __raw_readl(uart_base + UART_SYSCFG_OFFSET);    regVal |= UART_RESET;    __raw_writel(regVal, (uart_base + UART_SYSCFG_OFFSET) );    while ((__raw_readl(uart_base + UART_SYSSTS_OFFSET) &            UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK);     /* Disable smart idle */    regVal = __raw_readl((uart_base + UART_SYSCFG_OFFSET));    regVal |= UART_SMART_IDLE_EN;    __raw_writel(regVal, (uart_base + UART_SYSCFG_OFFSET));  <PATH : /arch/arm/include/asm/arch-ti81xx/cpu.h>#ifdef CONFIG_AM335X#define DEFAULT_UART_BASE       UART0_BASE#endif <PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h>#ifdef CONFIG_AM335X#define UART0_BASE          0x44E09000#else#define UART0_BASE          0x48020000#endif

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c6@ 初始化 定时器

123456789101112131415161718192021222324252627     /* Initialize the Timer */    init_timer();  <PATH : /board/ti/am335x/evm.c>static void init_timer(void){    /* Reset the Timer */    __raw_writel(0x2, (DM_TIMER2_BASE + TSICR_REG));     /* Wait until the reset is done */    while (__raw_readl(DM_TIMER2_BASE + TIOCP_CFG_REG) & 1);     /* Start the Timer */    __raw_writel(0x1, (DM_TIMER2_BASE + TCLR_REG));} <PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h>/* DM Timer base addresses */#define DM_TIMER0_BASE          0x4802C000#define DM_TIMER1_BASE          0x4802E000#define DM_TIMER2_BASE          0x48040000#define DM_TIMER3_BASE          0x48042000#define DM_TIMER4_BASE          0x48044000#define DM_TIMER5_BASE          0x48046000#define DM_TIMER6_BASE          0x48048000#define DM_TIMER7_BASE          0x4804A000

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c7@ 初始化控制台,通过UART可以查看相关信息

123456789101112131415161718192021222324     preloader_console_init(); 《PATH : /arch/arm/cpu/armv7/omap-common/spl.c》/* This requires UART clocks to be enabled */void preloader_console_init(void){    const char *u_boot_rev = U_BOOT_VERSION;    char rev_string_buffer[50];     gd = &gdata;    gd->bd = &bdata;    gd->flags |= GD_FLG_RELOC;    gd->baudrate = CONFIG_BAUDRATE;     serial_init();      /* serial communications setup */     /* Avoid a second "U-Boot" coming from this string */    u_boot_rev = &u_boot_rev[7];     printf("\nU-Boot SPL %s (%s - %s)\n", u_boot_rev, U_BOOT_DATE,        U_BOOT_TIME);    omap_rev_string(rev_string_buffer);    printf("Texas Instruments %s\n", rev_string_buffer);} <span style="font-size:14px;color:#003399;"></span>

                    @c8@ 配置 DDR

12345678910111213141516171819202122232425262728293031323334353637383940414243     config_am335x_ddr(); 《PATH :》/*  void DDR2_EMIF_Config(void); */static void config_am335x_ddr(void){    int data_macro_0 = 0;    int data_macro_1 = 1;     enable_ddr_clocks();     config_vtp();     Cmd_Macro_Config();     Data_Macro_Config(data_macro_0);    Data_Macro_Config(data_macro_1);     __raw_writel(PHY_RANK0_DELAY, DATA0_RANK0_DELAYS_0);    __raw_writel(PHY_RANK0_DELAY, DATA1_RANK0_DELAYS_0);     __raw_writel(DDR_IOCTRL_VALUE, DDR_CMD0_IOCTRL);    __raw_writel(DDR_IOCTRL_VALUE, DDR_CMD1_IOCTRL);    __raw_writel(DDR_IOCTRL_VALUE, DDR_CMD2_IOCTRL);    __raw_writel(DDR_IOCTRL_VALUE, DDR_DATA0_IOCTRL);    __raw_writel(DDR_IOCTRL_VALUE, DDR_DATA1_IOCTRL);     __raw_writel(__raw_readl(DDR_IO_CTRL) & 0xefffffff, DDR_IO_CTRL);    __raw_writel(__raw_readl(DDR_CKE_CTRL) | 0x00000001, DDR_CKE_CTRL);     config_emif_ddr2();}  《PATH : /arm/include/asm/arch-ti81xx/cpu.h》#define DATA0_RANK0_DELAYS_0        (DDR_PHY_BASE_ADDR + 0x134)#define DATA1_RANK0_DELAYS_0        (DDR_PHY_BASE_ADDR + 0x1D8) /* DDR offsets */#define DDR_PHY_BASE_ADDR       0x44E12000#define DDR_IO_CTRL         0x44E10E04#define DDR_CKE_CTRL            0x44E1131C#define CONTROL_BASE_ADDR       0x44E10000

转:AM335x启动流程(BootRom->MLO->Uboot)

                    @c DONE@

            @b DONE@

    @a4@ 设置 internal RAM 内存空间的栈指针,调用 board_init_f()函数

123456 /* 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
1234567891011121314151617181920212223242526 <PATH: include/configs/am335x_evm.h>#define CONFIG_SYS_INIT_SP_ADDR     (CONFIG_SYS_INIT_RAM_ADDR + \                     CONFIG_SYS_INIT_RAM_SIZE - \                     GENERATED_GBL_DATA_SIZE) #define CONFIG_SYS_INIT_RAM_ADDR    SRAM0_START#define CONFIG_SYS_INIT_RAM_SIZE    SRAM0_SIZE <PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h : begin>#ifdef CONFIG_AM335X#define SRAM0_START         0x402F0400#else#define SRAM0_START         0x40300000#endif<PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h : end> <PATH : /arch/arm/include/asm/arch-ti81xx/cpu.h : begin>#if defined(CONFIG_AM335X) || defined(CONFIG_TI814X)#define SRAM0_SIZE          (0x1B400) /* 109 KB */#define SRAM_GPMC_STACK_SIZE        (0x40)#endif<PATH : /arch/arm/include/asm/arch-ti81xx/cpu.h : end> <PATH : /am335x/include/generated/generic-asm-offsets.h : begin>#define GENERATED_GBL_DATA_SIZE (128) /* (sizeof(struct global_data) + 15) & ~15 */<PATH : /am335x/include/generated/generic-asm-offsets.h : end>
12345678910111213141516171819202122 <PATH : /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);} <PATH : /arch/arm/cpu/armv7/omap-common/spl.c : begin>#define CONFIG_SPL_TEXT_BASE        0x402F0400#define CONFIG_SPL_MAX_SIZE     (46 * 1024)#define CONFIG_SPL_STACK        LOW_LEVEL_SRAM_STACK<PATH : /arch/arm/cpu/armv7/omap-common/spl.c : end> <PATH : /arch/arm/include/asm/arch-ti81xx/omap.h : begin>#define LOW_LEVEL_SRAM_STACK    0x4030B7FC<PATH : /arch/arm/include/asm/arch-ti81xx/omap.h : end>
12345678910111213 <PATH : /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_coderelocate_code:    mov r4, r0  /* save addr_sp */    mov r5, r1  /* save addr of gd */    mov r6, r2  /* save addr of destination 0x402F0400*/

    @a5@ 代码重定位

代码重定向,它首先检测自己(MLO)是否已经在内存中:

如果是直接跳到下面的堆栈初始化代码 clear_bss。

如果不是就将自己从Nor Flash中拷贝到内存中。

Nor Flash 和Nand Flash 本质区别就在于是否进行代码拷贝,也就是下面代码所表述:无论
是Nor Flash 还是Nand Flash,核心思想就是将 uboot 代码搬运到内存中去运行,但是没有拷
贝bss 后面这段代码,只拷贝bss 前面的代码,bss 代码是放置全局变量的。Bss 段代码是为
了清零,拷贝过去再清零重复操作。

1234567891011121314151617     /* 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

    @a6@ 清空 bss 段

123456789101112131415161718192021 clear_bss:     ldr r0, _bss_start_ofs    ldr r1, _bss_end_ofs    mov r4, r6          /* reloc addr */    add r0, r0, r4    add r1, r1, r4     mov r2, #0x00000000     /* clear                */ clbss_l:str r2, [r0]        /* clear loop...            */    add r0, r0, #4    cmp r0, r1    bne clbss_l /* * These are defined in the board-specific linker script. */.globl _bss_start_ofs_bss_start_ofs:    .word __bss_start - _start          /* __bss_start = 0x80000000 */

    @a7@ 调用函数 board_init_r,用以完成 MLO(SPI)阶段的所有初始化,并跳转到 uboot.img 阶段

12345678910111213141516171819202122232425 /* * 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 《PATH : /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");     timer_init();    i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); #ifdef CONFIG_SPL_BOARD_INIT    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    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();    }}

    @a DONE@

3,第三级 bootloader:uboot.img 做了哪些事情?

uboot.img 内存分布如下:

转:AM335x启动流程(BootRom->MLO->Uboot)

转:AM335x启动流程(BootRom->MLO->Uboot)

访问 /arch/arm/lib/board.c 中 的 board_init_f() 函数

在 uboot.img 运行过程中,有两个非常重要的结构体:gd_t 和 bd_t 。

其中 gd_t :global_data 数据结构的定义,位于:/arch/arm/include/asm/global_data.h 中。

其成员主要是一些全局的系统初始化参数。

其中 bd_t :bd_info 数据结构的定义,位于:/arch/arm/include/asm/u-boot.h 中。

其成员是开发板的相关参数。

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 <PATH : /arch/arm/include/asm/global_data.h >/* * The following data structure is placed in some memory which is * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or * some locked parts of the data cache) to allow for a minimum set of * global variables during system initialization (until we have set * up the memory controller so that we can use RAM). * * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE > sizeof(gd_t) */ typedef struct  global_data {    bd_t        *bd;    unsigned long   flags;    unsigned long   baudrate;    unsigned long   have_console;   /* serial_init() was called */    unsigned long   env_addr;   /* Address  of Environment struct */    unsigned long   env_valid;  /* Checksum of Environment valid? */    unsigned long   fb_base;    /* base address of frame buffer */#ifdef CONFIG_FSL_ESDHC    unsigned long   sdhc_clk;#endif#ifdef CONFIG_AT91FAMILY    /* "static data" needed by at91's clock.c */    unsigned long   cpu_clk_rate_hz;    unsigned long   main_clk_rate_hz;    unsigned long   mck_rate_hz;    unsigned long   plla_rate_hz;    unsigned long   pllb_rate_hz;    unsigned long   at91_pllb_usb_init;#endif#ifdef CONFIG_ARM    /* "static data" needed by most of timer.c on ARM platforms */    unsigned long   timer_rate_hz;    unsigned long   tbl;    unsigned long   tbu;    unsigned long long  timer_reset_value;    unsigned long   lastinc;#endif#ifdef CONFIG_IXP425    unsigned long   timestamp;#endif    unsigned long   relocaddr;  /* Start address of U-Boot in RAM */    phys_size_t ram_size;   /* RAM size */    unsigned long   mon_len;    /* monitor len */    unsigned long   irq_sp;     /* irq stack pointer */    unsigned long   start_addr_sp;  /* start_addr_stackpointer */    unsigned long   reloc_off;#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))    unsigned long   tlb_addr;#endif    void        **jt;       /* jump table */    char        env_buf[32];    /* buffer for getenv() before reloc. */} gd_t; #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")  <PATH : /arch/arm/include/asm/u-boot.h >typedef struct bd_info {    int         bi_baudrate;    /* serial console baudrate */    unsigned long   bi_ip_addr; /* IP Address */    ulong           bi_arch_number; /* unique id for this board */    ulong           bi_boot_params; /* where this board expects params */    struct              /* RAM configuration */    {    ulong start;    ulong size;    }           bi_dram[CONFIG_NR_DRAM_BANKS];} bd_t;

其中 DECLARE_GLOBAL_DATA_PTR 宏定义在系统初始化过程中会被频繁调用,

的作用是,声明gd这么一个全局的指针,这个指针指向gd_t结构体类型,并且这个gd指针是保存在ARM的r8这个寄存器里面的。

 

uboot.img 第一个运行的文件还是 start.o,其在运行访问的 board_init_f() 函数定义在 /arch/arm/lib/board.c 中:

1234567891011121314151617 <PATH : /arch/arm/lib/board.c >void board_init_f(ulong bootflag){    bd_t *bd;    init_fnc_t **init_fnc_ptr;    gd_t *id;    ulong addr, addr_sp;     /* Pointer is writable since we allocated a register for it */    gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);    /* compiler optimization barrier needed for GCC >= 3.4 */    __asm__ __volatile__("": : :"memory");     memset((void *)gd, 0, sizeof(gd_t));         ...}
123456789101112131415 <PATH : /include/configs/am335x_evm>#define CONFIG_SYS_INIT_RAM_ADDR    SRAM0_START#define CONFIG_SYS_INIT_RAM_SIZE    SRAM0_SIZE#define CONFIG_SYS_INIT_SP_ADDR     (CONFIG_SYS_INIT_RAM_ADDR + \                     CONFIG_SYS_INIT_RAM_SIZE - \                     GENERATED_GBL_DATA_SIZE) <PATH : /arch/arm/include/asm/arch-ti81xx/hardware.h>#define SRAM0_START         0x402F0400 <PATH : /arch/arm/include/asm/arch-ti81xx/cpu.h>#define SRAM0_SIZE          (0x1B400) /* 109 KB */ <PATH : /am335x/include/generated/generic-asm-offsets.h>#define GENERATED_GBL_DATA_SIZE (128) /* (sizeof(struct global_data) + 15) & ~15 */

因此,系统初始化参数将会被保存在 (保存 MLO(SPL)文件的内存空间的)末尾 2 KB 处。

通过计算的 gb 指针指向的内存空间地址为 gb = 0x4030B000

转:AM335x启动流程(BootRom->MLO->Uboot)

gb_t 结构体中某些元素的值是来自于 uboot.img’s header,这个header的数据保存在内存的0x807FFFCO,大小为 64字节

12345678910111213141516171819 <PATH : /include/image.h>/* * Legacy format image header, * all data in network byte order (aka natural aka bigendian). */typedef struct image_header {    uint32_t    ih_magic;   /* Image Header Magic Number    */    uint32_t    ih_hcrc;    /* Image Header CRC Checksum    */    uint32_t    ih_time;    /* Image Creation Timestamp */    uint32_t    ih_size;    /* Image Data Size      */    uint32_t    ih_load;    /* Data  Load  Address      */    uint32_t    ih_ep;      /* Entry Point Address      */    uint32_t    ih_dcrc;    /* Image Data CRC Checksum  */    uint8_t     ih_os;      /* Operating System     */    uint8_t     ih_arch;    /* CPU architecture     */    uint8_t     ih_type;    /* Image Type           */    uint8_t     ih_comp;    /* Compression Type     */    uint8_t     ih_name[IH_NMLEN];  /* Image Name       */} image_header_t;
12345678 <PATH : /include/configs/am335x_evm.h>/* * 8MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM. * 64 bytes before this address should be set aside for u-boot.img's * header. That is 0x807FFFC0--0x80800000 should not be used for any * other needs. */#define CONFIG_SYS_TEXT_BASE        0x80800000
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,487
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,127
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,289