AM335x SPL

原文地址:AM335x SPL 作者:Peter_Lee_CN

(一)

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,则分布图如下:


 

  1. +------------+-->0x00000000-> SPL start (SPL copy on 1st block)
  2. |            |
  3. |            |-->0x0001FFFF-> SPL end 
  4. |            |-->0x00020000-> SPL.backup1 start (SPL copy on 2nd block)
  5. |            |
  6. |            |-->0x0003FFFF-> SPL.backup1 end 
  7. |            |-->0x00040000-> SPL.backup2 start (SPL copy on 3rd block)
  8. |            |
  9. |            |-->0x0005FFFF-> SPL.backup2 end 
  10. |            |-->0x00060000-> SPL.backup3 start (SPL copy on 4th block)
  11. |            |
  12. |            |-->0x0007FFFF-> SPL.backup3 end
  13. |            |-->0x00080000-> U-Boot start
  14. |            | 
  15. |            |-->0x002BFFFF-> U-Boot end 
  16. |            |-->0x00260000-> ENV start
  17. |            |
  18. |            |
  19. |            |-->0x0027FFFF-> ENV end
  20. |            |-->0x00280000-> Linux Kernel start
  21. |            |
  22. |            |
  23. |            |
  24. |            |
  25. |            |-->0x0077FFFF-> Linux Kernel end
  26. |            |-->0x00780000-> File system start
  27. |            |
  28. |            |
  29. |            |
  30. |            |
  31. |            |
  32. |            |
  33. |            |
  34. |            |
  35. |            |
  36. |            |
  37. |            |
  38. |            |
  39. +------------+-->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目录下:

clip_image002

clip_image002[6]

clip_image002[8]

clip_image002[10]

通过上面的图,可以很清楚的了解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 Subsystem PLL Structure_1

配置MPU PLL

Configuring the 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

配置Core PLL

Core PLL Configuration

代码如下:

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 Structure

配置Peripheral PLL

Configuring the 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信息如下:

image

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个部分需要设置,如下:

image

 

 

DDR PLL 结构:

image

配置DDR PLL:

image

image

代码如下:

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.Sboard_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.cvoid 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&gdataCONFIG_SPL_TEXT_BASE);

其中r0,r1,r2r0 :  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                        01MB      à //定时器初始化,使用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.cvoid 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时会自动编译。  image  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大小。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值