Chinaunix首页 | 论坛 | 博客
  • 博客访问: 610731
  • 博文数量: 168
  • 博客积分: 1053
  • 博客等级: 少尉
  • 技术积分: 1187
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-30 17:20
个人简介

公众号【嵌入式er笔记】持续记录和分享C/C++、Linux、ARM、Android、IoT等技术相关知识,以及职场、生活经验和感悟。

文章分类

全部博文(168)

分类: 嵌入式

2013-03-12 17:56:49

原文地址: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                        //初始化内存,设为00x80208000开始,大小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_BOARDIA_BOARDIPP_BOARD(板卡有两部分组成)

BONE_BOARDSK_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,

beaglebonestarterkit为例:

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



阅读(4082) | 评论(0) | 转发(0) |
0

上一篇:AM335x SPL(三)

下一篇:AM335x bootloader

给主人留下些什么吧!~~