u-boot分析之 DDR配置

来源:互联网 发布:局域网视频通话软件 编辑:程序博客网 时间:2024/05/17 04:23

    继上篇文章介绍u-boot分析之u-boot.lds脚本分析之后,我们接着需要了解下关于DDR初始化方面的,以方便后续的对z-turnkaU-boot移植工作.


大家都知道,uboot启动至命令行几个重要函数为:_start,_main,board_init_f,relocate_code,board_init_r,下面我们进行一一分析。

一 _start

    对于任何程序,入口函数是在链接时决定的,uboot的入口是由链接脚本决定的。uboot下armv7链接脚本默认目录为arch/arm/cpu/u-boot.lds。这个可以在配置文件中与CONFIG_SYS_LDSCRIPT来指定。

reset异常是直接跳转到reset函数,其他7种异常是用ldr将处理函数入口地址加载到pc中。

1 初始化异常向量表   2 设置cpu svc模式,关中断    3 配置cp15,设置异常向量入口
cpu_init_cp15函数是配置cp15协处理器相关寄存器来设置处理器的MMU,cache以及tlb。如果没有定义CONFIG_SYS_ICACHE_OFF则会打开icache。关掉mmu以及tlb。

G:\sftp\c3001\c300\uboot\include\configs\c300evm.h (1 hit)
    Line 53: #define PHYS_SDRAM_1_SIZE(1024 * 1024 * 1024)

  G:\sftp\c3001\c300\uboot\cpu\arm1136\start.S (3 hits)
    Line 74: _TEXT_BASE:
    .word    TEXT_BASE

  G:\sftp\c3001\c300\uboot\board\mindspeed\c300evm\config.mk (1 hit)
    Line 4: TEXT_BASE = 0x07E00000    # 126MiB

reset

[cpp] view plain copy
  1. reset:  
  2. #if defined(CONFIG_COMCERTO_300)  
  3. #ifndef CONFIG_SKIP_RELOCATE_UBOOT  
  4.     /* If booting from external boot ROM we are at address 0x00000000 and 
  5.      * must jump to CS2 range 0x11000000 before disabling the low 
  6.      * memory aliasing. If booting from IBR we are already at high address 
  7.      * and there is nothing to do. 
  8.      */  
  9.     mov    r0, pc  
  10.     ldr    r2, =reset - TEXT_BASE + 8  
  11.     cmp    r0, r2  
  12.   
  13.     ldreq    pc, =COMCERTO_CS2_BASE + rom_second_loc - TEXT_BASE  
  14. #endif  
  15. rom_second_loc:  
  16.     /* we are running in CS2 range, it's safe to disable ROM remapping, 
  17.      * just keep CS2 enabled for now 
  18.      */  
  19.     ldr    r2, =COMCERTO_DECODER_CSE  
  20.     ldr    r3, [r2]  
  21.     bic    r3, #DECODER_CSE_ROM_REMAP_ENABLE  
  22.     strh    r3, [r2]  
  23. #endif  
  24.   
  25.     /* 
  26.      * set the cpu to SVC32 mode 
  27.      */  
  28.     mrs    r0,cpsr  
  29.     bic    r0,r0,#0x1f  
  30.     orr    r0,r0,#0xd3  
  31.     msr    cpsr,r0  
  32.   
  33. #ifdef CONFIG_OMAP2420H4  
  34.        /* Copy vectors to mask ROM indirect addr */  
  35.     adr    r0, _start        /* r0 <- current position of code   */  
  36.          add     r0, r0, #4                /* skip reset vector            */  
  37.     mov    r2, #64            /* r2 <- size to copy  */  
  38.     add    r2, r0, r2        /* r2 <- source end address        */  
  39.     mov    r1, #SRAM_OFFSET0      /* build vect addr */  
  40.     mov    r3, #SRAM_OFFSET1  
  41.     add    r1, r1, r3  
  42.     mov    r3, #SRAM_OFFSET2  
  43.     add    r1, r1, r3  
  44. next:  
  45.     ldmia    r0!, {r3-r10}        /* copy from source address [r0]    */  
  46.     stmia    r1!, {r3-r10}        /* copy to   target address [r1]    */  
  47.     cmp    r0, r2            /* until source end address [r2]    */  
  48.     bne    next            /* loop until equal */  
  49.     bl    cpy_clk_code        /* put dpll adjust code behind vectors */  
  50. #endif  
  51.     /* the mask ROM code should have PLL and others stable */  
  52. #ifndef CONFIG_SKIP_LOWLEVEL_INIT  
  53.     bl    cpu_init_crit  
  54. #endif  
  55.   
  56. #ifndef CONFIG_SKIP_RELOCATE_UBOOT  
  57. relocate:                /* relocate U-Boot to RAM        */  
  58.     adr    r0, _start        /* r0 <- current position of code   */  
  59.     ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */  
  60.     cmp    r0, r1            /* don't reloc during debug        */  
  61.     beq    stack_setup  
  62.   
  63.     ldr    r2, _armboot_start  
  64.     ldr    r3, _bss_start  
  65.     sub    r2, r3, r2        /* r2 <- size of armboot        */  
  66.     add    r2, r0, r2        /* r2 <- source end address        */  
  67.   
  68. copy_loop:  
  69.     ldmia    r0!, {r3-r10}        /* copy from source address [r0]    */  
  70.     stmia    r1!, {r3-r10}        /* copy to   target address [r1]    */  
  71.     cmp    r0, r2            /* until source end addreee [r2]    */  
  72.     ble    copy_loop  
  73. #endif    /* CONFIG_SKIP_RELOCATE_UBOOT */  
  74.   
  75.     /* Set up the stack                            */  
  76. stack_setup:  
  77.     ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */  
  78.     sub    r0, r0, #CFG_MALLOC_LEN /* malloc area                */  
  79.     sub    r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                */  
  80. #ifdef CONFIG_USE_IRQ  
  81.     sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)  
  82. #endif  
  83.     sub    sp, r0, #12        /* leave 3 words for abort-stack    */  
  84.   
  85. clear_bss:  
  86.     ldr    r0, _bss_start        /* find start of bss segment        */  
  87.     ldr    r1, _bss_end        /* stop here                */  
  88.     mov    r2, #0x00000000        /* clear                */  
  89.   
  90. clbss_l:str    r2, [r0]        /* clear loop...            */  
  91.     add    r0, r0, #4  
  92.     cmp    r0, r1  
  93.     bne    clbss_l  
  94.   
  95.     ldr    pc, _start_armboot  
  96.   
  97. _start_armboot: .word start_armboot  

cpu_init_crit

[cpp] view plain copy
  1. cpu_init_crit:  
  2.     /* 
  3.      * flush v4 I/D caches 
  4.      */  
  5.     mov r0, #0  
  6.     mcr p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */  
  7.     mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */  
  8.   
  9.     /* 
  10.      * disable MMU stuff and caches 
  11.      */  
  12.     mrc p15, 0, r0, c1, c0, 0  
  13.     bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)  
  14.     bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)  
  15.     orr r0, r0, #0x00000002 @ set bit 2 (A) Align  
  16.     orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache  
  17.     orr r0, r0, #0x00400000 @ set bit 22 (U)   
  18.     mcr p15, 0, r0, c1, c0, 0  
  19.   
  20.     /* 
  21.      * Jump to board specific initialization... The Mask ROM will have already initialized 
  22.      * basic memory.  Go here to bump up clock rate and handle wake up conditions. 
  23.      */  
  24.     mov ip, lr      /* persevere link reg across call */  
  25.     bl  lowlevel_init   /* go setup pll,mux,memory */  
  26.     mov lr, ip      /* restore link */  
  27.     mov pc, lr      /* back to my caller */  





cpu_init_crit调用的lowlevel_init函数是与特定开发板相关的初始化函数,在这个函数里会做一些pll初始化,如果不是从mem启动,则会做memory初始化,方便后续拷贝到mem中运行。

lowlevel_init

[cpp] view plain copy
  1. lowlevel_init:  
  2.     ldr    sp, TMP_STACK    /* set up a temporary stack */  
  3.   
  4.     stmdb    sp!, {ip, lr}  
  5.     bl    bsp_init    /* go setup pll, memory */  
  6.     ldmia    sp!, {ip, pc}    /* restore registers and return to caller */  
  7.   
  8.     /* the literal pools origin */  
  9.     .ltorg  
  10. TMP_STACK:  
  11.     .word    CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET  
  12.   
  13. #define CFG_INIT_RAM_ADDR        ARAM_MEMORY_PHY  
  14. #define CFG_INIT_SP_OFFSET        0x1000  
  15.   
  16. #define ARAM_MEMORY_PHY            0x0A000000   

bsp_init

[cpp] view plain copy
  1. void bsp_init(void)  
  2. {  
  3.     comcerto300_init();  
  4.     comcerto300_pll_set_clocks(CFG_ARM_CLOCK, CFG_HZ_CLOCK, CFG_SPU_CLOCK);  
  5.   
  6.     /* setup SDRAM controller, values are design specific */  
  7.     writel(0xD2DE, COMCERTO_SDC_SDRAM_CFG1);  
  8.     writel(0x0820, COMCERTO_SDC_SDRAM_REFRESH);  
  9.     writel(0x682B, COMCERTO_SDC_SDRAM_POWERON);  
  10.     writel(0x92CA, COMCERTO_SDC_SDRAM_CFG2);  
  11.   
  12.     /* setup SDRAM - it on CS0 only for C300EVM */  
  13.     comcerto300_set_cs_type(0, 1);                  /* allow access to SDRAM via CS0 */  
  14.     comcerto300_set_cs_region(0, PHYS_SDRAM, PHYS_SDRAM_SIZE);  /* define memory region for CS0 */  
  15.     comcerto300_set_cse(0, 1);                  /* enable CS0 */  
  16.   
  17.     icache_enable();  
  18. }  
    \uboot\lib_arm\board.c (1 hit)
     void start_armboot (void)

start_armboot

[cpp] view plain copy
  1. void start_armboot (void)  
  2. {  
  3.     init_fnc_t **init_fnc_ptr;  
  4.     char *s;  
  5. #ifndef CFG_NO_FLASH  
  6.     ulong size;  
  7. #endif  
  8. #if defined(CONFIG_VFD) || defined(CONFIG_LCD)  
  9.     unsigned long addr;  
  10. #endif  
  11.   
  12.     /* Pointer is writable since we allocated a register for it */  
  13.     gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));  
  14.     /* compiler optimization barrier needed for GCC >= 3.4 */  
  15.     __asm__ __volatile__("": : :"memory");  
  16.   
  17.     memset ((void*)gd, 0, sizeof (gd_t));  
  18.     gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));  
  19.     memset (gd->bd, 0, sizeof (bd_t));  
  20.   
  21.     monitor_flash_len = _bss_start - _armboot_start;  
  22.   
  23.     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {  
  24.         if ((*init_fnc_ptr)() != 0) {  
  25.             hang ();  
  26.         }  
  27.     }  
  28.   
  29. #ifndef CFG_NO_FLASH  
  30.     /* configure available FLASH banks */  
  31.     size = flash_init ();  
  32.     display_flash_config (size);  
  33. #endif /* CFG_NO_FLASH */  
  34.   
  35. #ifdef CONFIG_VFD  
  36. #   ifndef PAGE_SIZE  
  37. #     define PAGE_SIZE 4096  
  38. #   endif  
  39.     /* 
  40.      * reserve memory for VFD display (always full pages) 
  41.      */  
  42.     /* bss_end is defined in the board-specific linker script */  
  43.     addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);  
  44.     size = vfd_setmem (addr);  
  45.     gd->fb_base = addr;  
  46. #endif /* CONFIG_VFD */  
  47.   
  48. #ifdef CONFIG_LCD  
  49. #   ifndef PAGE_SIZE  
  50. #     define PAGE_SIZE 4096  
  51. #   endif  
  52.     /* 
  53.      * reserve memory for LCD display (always full pages) 
  54.      */  
  55.     /* bss_end is defined in the board-specific linker script */  
  56.     addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);  
  57.     size = lcd_setmem (addr);  
  58.     gd->fb_base = addr;  
  59. #endif /* CONFIG_LCD */  
  60.   
  61.     /* armboot_start is defined in the board-specific linker script */  
  62.     mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);  
  63.   
  64. #if (CONFIG_COMMANDS & CFG_CMD_NAND)  
  65.     puts ("NAND:  ");  
  66.     nand_init();        /* go init the NAND */  
  67. #endif  
  68.   
  69. #ifdef CONFIG_HAS_DATAFLASH  
  70.     AT91F_DataflashInit();  
  71.     dataflash_print_info();  
  72. #endif  
  73.   
  74.     /* initialize environment */  
  75.     env_relocate ();   
  76.   
  77. #ifdef CONFIG_VFD  
  78.     /* must do this after the framebuffer is allocated */  
  79.     drv_vfd_init();  
  80. #endif /* CONFIG_VFD */  
  81.   
  82.     /* IP Address */  
  83.     gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");  
  84.   
  85.     /* MAC Address */  
  86.     {  
  87.         int i;  
  88.         ulong reg;  
  89.         char *s, *e;  
  90.         char tmp[64];  
  91.   
  92.         i = getenv_r ("ethaddr", tmp, sizeof (tmp));  
  93.         s = (i > 0) ? tmp : NULL;  
  94.   
  95.         for (reg = 0; reg < 6; ++reg) {  
  96.             gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;  
  97.             if (s)  
  98.                 s = (*e) ? e + 1 : e;  
  99.         }  
  100.   
  101. #ifdef CONFIG_HAS_ETH1  
  102.         i = getenv_r ("eth1addr", tmp, sizeof (tmp));  
  103.         s = (i > 0) ? tmp : NULL;  
  104.   
  105.         for (reg = 0; reg < 6; ++reg) {  
  106.             gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;  
  107.             if (s)  
  108.                 s = (*e) ? e + 1 : e;  
  109.         }  
  110. #endif  
  111.     }  
  112.   
  113.     devices_init ();    /* get the devices list going. */  
  114.   
  115. #ifdef CONFIG_CMC_PU2  
  116.     load_sernum_ethaddr ();  
  117. #endif /* CONFIG_CMC_PU2 */  
  118.   
  119.     jumptable_init ();  
  120.   
  121.     console_init_r ();  /* fully init console as a device */  
  122.   
  123. #if defined(CONFIG_MISC_INIT_R)  
  124.     /* miscellaneous platform dependent initialisations */  
  125.     misc_init_r ();  
  126. #endif  
  127.   
  128.     /* enable exceptions */  
  129.     enable_interrupts ();  
  130.   
  131.     /* Perform network card initialisation if necessary */  
  132. #ifdef CONFIG_DRIVER_CS8900  
  133.     cs8900_get_enetaddr (gd->bd->bi_enetaddr);  
  134. #endif  
  135.   
  136. #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)  
  137.     if (getenv ("ethaddr")) {  
  138.         smc_set_mac_addr(gd->bd->bi_enetaddr);  
  139.     }  
  140. #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */  
  141.   
  142.     /* Initialize from environment */  
  143.     if ((s = getenv ("loadaddr")) != NULL) {  
  144.         load_addr = simple_strtoul (s, NULL, 16);  
  145.     }  
  146. #if (CONFIG_COMMANDS & CFG_CMD_NET)  
  147.     if ((s = getenv ("bootfile")) != NULL) {  
  148.         copy_filename (BootFile, s, sizeof (BootFile));  
  149.     }  
  150. #endif  /* CFG_CMD_NET */  
  151.   
  152. #ifdef BOARD_LATE_INIT  
  153.     board_late_init ();  
  154. #endif  
  155. #if (CONFIG_COMMANDS & CFG_CMD_NET)  
  156. #if defined(CONFIG_NET_MULTI)  
  157.     puts ("Net:   ");  
  158. #endif  
  159.     eth_initialize(gd->bd);  
  160. #endif  
  161.     /* main_loop() can return to retry autoboot, if so just run it again. */  
  162.     for (;;) {  
  163.         main_loop ();  
  164.     }  
  165.   
  166.     /* NOTREACHED - no way out of command loop except booting */  
  167. }  


init_sequence

[cpp] view plain copy
  1. init_fnc_t *init_sequence[] = {  
  2.     cpu_init,       /* basic cpu dependent setup */  
  3.     board_init,     /* basic board dependent setup */  
  4.     interrupt_init,     /* set up exceptions */  
  5.     env_init,       /* initialize environment */  
  6.     init_baudrate,      /* initialze baudrate settings */  
  7.     serial_init,        /* serial communications setup */  
  8.     console_init_f,     /* stage 1 init of console */  
  9.     display_banner,     /* say that we are here */  
  10. #if defined(CONFIG_DISPLAY_CPUINFO)  
  11.     print_cpuinfo,      /* display cpu info (and speed) */  
  12. #endif  
  13. #if defined(CONFIG_DISPLAY_BOARDINFO)  
  14.     checkboard,     /* display board info */  
  15. #endif  
  16.     dram_init,      /* configure available RAM banks */  
  17.     display_dram_config,  
  18.     NULL,  
  19. };  


display_banner是第一条打印语句

  \uboot\cpu\arm1136\cpu.c (1 hit)
    int cpu_init (void)

cpu_init

[cpp] view plain copy
  1. int cpu_init (void)  
  2. {  
  3.     /* 
  4.      * setup up stacks if necessary 
  5.      */  
  6. #ifdef CONFIG_USE_IRQ  
  7.     IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;  
  8.     FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;  
  9. #endif  
  10.     return 0;  
  11. }  

   \uboot\board\xilinx\zynq\board.c
     int board_init(void)

board_init

[cpp] view plain copy
  1. static void nor_init(void)  
  2. {  
  3.     u32 cs1_base = PHYS_FLASH2, fcs_base = PHYS_FLASH1;  
  4.     u32 cs1_size = 64*1024*1024, fcs_size = 1*1024*1024;  
  5.     u32 cs_nor8=2, cs_nor16=1;  
  6.   
  7.     /* 
  8.      * Supported types of boot from external flash: 
  9.      * 1. Direct boot from external NOR8 flash (CS2: NOR8, CS1: NOR16) 
  10.      * 2. Secondary boot via IBR from NOR8 (CS2: NOR8, CS1: NOR16) 
  11.      * 3. Secondary boot via IBR from NOR16 (CS2: NOR16, CS1: NOR8) 
  12.      * 
  13.      * To avoid messing with different types of flash at the one fixed 
  14.      * address (CS2 at 0x11000000) we use programmable FCS. CS1 is ok 
  15.      * since base address is not fixed. So, defaults are for the case 1) 
  16.      * and 2). If we detect case 3) we just swap default values. 
  17.      */  
  18.   
  19.     if ((readl(COMCERTO_GPIO_SYSTEM_CONFIG) & 2) != 0 && (readl(COMCERTO_GPIO_INPUT) & 0xE0) == 0x20) {  
  20.         u32 temp;  
  21.   
  22.         /* IBR NOR16 boot - map NOR8 on CS1, map NOR16 on CS2/FCS - just swap default cs stuff */  
  23.         temp = cs1_base, cs1_base = fcs_base, fcs_base = temp;  
  24.         temp = cs1_size, cs1_size = fcs_size, fcs_size = temp;  
  25.         temp = cs_nor8, cs_nor8 = cs_nor16, cs_nor16 = temp;  
  26.     }  
  27.   
  28.     comcerto300_uexp_cfg_cs(cs_nor8, 0x0090, 0x0095, 0x0301);  
  29.     comcerto300_uexp_cfg_cs(cs_nor16, 0x0910, 0x0895, 0x0820);  
  30.   
  31.     comcerto300_set_cs_region(1, cs1_base, cs1_size);  
  32.     comcerto300_set_fcs(1, 2, fcs_base, fcs_size);  
  33.   
  34.     comcerto300_set_cse(1, 1);  
  35.     comcerto300_set_cse(2, 1);  
  36. }  
  37.   
  38. int board_init(void)  
  39. {  
  40.     /* reset on-board peripherals via GPIO line */  
  41.     gpio_direction_output(CFG_GPIO_OUT_PERIPHERAL_RESET, 0);  
  42.     udelay(100);  
  43.     gpio_set_value(CFG_GPIO_OUT_PERIPHERAL_RESET, 1);  
  44.   
  45.     /* CS0 is used for SDRAM, see bsp_init() */  
  46.   
  47.     /* CS1 and CS2 used for flash memories  */  
  48.     nor_init();  
  49.   
  50.     /* CS3 - TSI */  
  51.     comcerto300_uexp_cfg_cs(3, 0xC910, 0x08A5, 0x083A);  
  52.     comcerto300_set_cse(3, 1);  
  53.   
  54.     /* CS4 - PLD */  
  55.     comcerto300_uexp_cfg_cs(4, 0x1106, 0x08A5, 0x083A);  
  56.     comcerto300_set_cse(4, 1);  
  57.   
  58.     /* CS5 - NAND */  
  59.     comcerto300_uexp_cfg_cs(5, 0x2108, 0x0895, 0x0820);  
  60.     comcerto300_set_cse(5, 1);  
  61.     gpio_direction_input(CFG_GPIO_IN_NAND_BR);  /* ready signal is connected to GPIO line */  
  62.   
  63. #if defined(CONFIG_TDM) || defined(CONFIG_TSI_MT90869)  
  64.     comcerto300_ntg_8mhz_init();  
  65. #endif  
  66.   
  67. #if (CONFIG_COMMANDS & CFG_CMD_SPI)  
  68.     spi_hw_init();  
  69. #endif  
  70.   
  71. #ifdef CONFIG_TSI_MT90869  
  72.     udelay(10*1000);  
  73.     tsi_hw_init((void*) COMCERTO_CS3_BASE);  
  74. #endif  
  75.   
  76.     return 0;  
  77. }  
  78.   
  79. int dram_init(void)  
  80. {  
  81.     gd->bd->bi_dram[0].start = PHYS_SDRAM;  
  82.     gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE;  
  83.   
  84.     return 0;  
  85. }  

  \ubootarch\arm\cpu\armv7\zynq\ interrupt_ini.c 
     int interrupt_init(void)

interrupt_init

[cpp] view plain copy
  1. int interrupt_init(void)  
  2. {  
  3.     writel(TIMER_LOAD_VAL, COMCERTO_TIMER0_HIGH_BOUND);  
  4.   
  5.     lastinc = 0;  
  6.     ts_count = 0;  
  7.     ts_usec = 0;  
  8.   
  9.     return 0;  
  10. }  


   \ubootarch\arm\cpu\armv7\zynq\interrupts.c 
    int interrupt_init (void)

[cpp] view plain copy
  1. /* nothing really to do with interrupts, just starts up a counter. */  
  2. int interrupt_init (void)  
  3. {  
  4.     int32_t val;  
  5.   
  6.     /* Start the counter ticking up */  
  7.     *((int32_t *) (CFG_TIMERBASE + TLDR)) = TIMER_LOAD_VAL; /* reload value on overflow*/  
  8.     val = (CFG_PVT << 2) | BIT5 | BIT1 | BIT0;        /* mask to enable timer*/  
  9.     *((int32_t *) (CFG_TIMERBASE + TCLR)) = val;    /* start timer */  
  10.   
  11.     reset_timer_masked(); /* init the timestamp and lastinc value */  
  12.   
  13.     return(0);  
  14. }  
    \uboot\common\env_flash.c (2 hits)
     int  env_init(void)
     int  env_init(void)
    \uboot\common\env_nand.c (1 hit)

     int env_init(void)

env_init

[cpp] view plain copy
  1. int env_init(void)  
  2. {  
  3. #if defined(ENV_IS_EMBEDDED)  
  4.     ulong total;  
  5.     int crc1_ok = 0, crc2_ok = 0;  
  6.     env_t *tmp_env1, *tmp_env2;  
  7.   
  8.     total = CFG_ENV_SIZE;  
  9.   
  10.     tmp_env1 = env_ptr;  
  11.     tmp_env2 = (env_t *)((ulong)env_ptr + CFG_ENV_SIZE);  
  12.   
  13.     crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);  
  14.     crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);  
  15.   
  16.     if (!crc1_ok && !crc2_ok)  
  17.         gd->env_valid = 0;  
  18.     else if(crc1_ok && !crc2_ok)  
  19.         gd->env_valid = 1;  
  20.     else if(!crc1_ok && crc2_ok)  
  21.         gd->env_valid = 2;  
  22.     else {  
  23.         /* both ok - check serial */  
  24.         if(tmp_env1->flags == 255 && tmp_env2->flags == 0)  
  25.             gd->env_valid = 2;  
  26.         else if(tmp_env2->flags == 255 && tmp_env1->flags == 0)  
  27.             gd->env_valid = 1;  
  28.         else if(tmp_env1->flags > tmp_env2->flags)  
  29.             gd->env_valid = 1;  
  30.         else if(tmp_env2->flags > tmp_env1->flags)  
  31.             gd->env_valid = 2;  
  32.         else /* flags are equal - almost impossible */  
  33.             gd->env_valid = 1;  
  34.     }  
  35.   
  36.     if (gd->env_valid == 1)  
  37.         env_ptr = tmp_env1;  
  38.     else if (gd->env_valid == 2)  
  39.         env_ptr = tmp_env2;  
  40. #else /* ENV_IS_EMBEDDED */  
  41.     gd->env_addr  = (ulong)&default_environment[0];  
  42.     gd->env_valid = 1;  
  43. #endif /* ENV_IS_EMBEDDED */  
  44.   
  45.     return (0);  
  46. }  
   \uboot\lib_arm\board.c (2 hits)
    static int init_baudrate (void)

init_baudrate

[cpp] view plain copy
  1. static int init_baudrate (void)  
  2. {  
  3.     char tmp[64];   /* long enough for environment variables */  
  4.     int i = getenv_r ("baudrate", tmp, sizeof (tmp));  
  5.     gd->bd->bi_baudrate = gd->baudrate = (i > 0)  
  6.             ? (int) simple_strtoul (tmp, NULL, 10)  
  7.             : CONFIG_BAUDRATE;  
  8.   
  9.     return (0);  
  10. }  

   \uboot\common\serial.c (1 hit)
    int serial_init (void)

serial_init

[cpp] view plain copy
  1. int serial_init (void)  
  2. {  
  3.     if (!(gd->flags & GD_FLG_RELOC) || !serial_current) {  
  4.         struct serial_device *dev = default_serial_console ();  
  5.   
  6.         return dev->init ();  
  7.     }  
  8.   
  9.     return serial_current->init ();  
  10. }  

  \uboot\common\serial.c (8 hits)
   struct serial_device *default_serial_console (void)

default_serial_console

[cpp] view plain copy
  1. #ifndef CONFIG_LWMON  
  2. struct serial_device *default_serial_console (void)  
  3. {  
  4. #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2)  
  5.     return &serial_smc_device;  
  6. #elif defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \  
  7.    || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)  
  8.     return &serial_scc_device;  
  9. #elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) \  
  10.    || defined(CONFIG_405EP) || defined(CONFIG_MPC5xxx)  
  11. #if defined(CONFIG_CONS_INDEX) && defined(CFG_NS16550_SERIAL)  
  12. #if (CONFIG_CONS_INDEX==1)  
  13.     return &eserial1_device;  
  14. #elif (CONFIG_CONS_INDEX==2)  
  15.     return &eserial2_device;  
  16. #elif (CONFIG_CONS_INDEX==3)  
  17.     return &eserial3_device;  
  18. #elif (CONFIG_CONS_INDEX==4)  
  19.     return &eserial4_device;  
  20. #else  
  21. #error "Bad CONFIG_CONS_INDEX."  
  22. #endif  
  23. #elif defined(CONFIG_UART1_CONSOLE)  
  24.         return &serial1_device;  
  25. #else  
  26.         return &serial0_device;  
  27. #endif  
  28. #else  
  29. #error No default console  
  30. #endif  
  31. }  
  32. #endif  

 \uboot\include\serial.h (11 hits)
  struct serial_device {

struct serial_device

[cpp] view plain copy
  1. struct serial_device {  
  2.     char name[NAMESIZE];  
  3.     char ctlr[CTLRSIZE];  
  4.   
  5.     int  (*init) (void);  
  6.     void (*setbrg) (void);  
  7.     int (*getc) (void);  
  8.     int (*tstc) (void);  
  9.     void (*putc) (const char c);  
  10.     void (*puts) (const char *s);  
  11.   
  12.     struct serial_device *next;  
  13. };  


\uboot\drivers\serial.c 
   int serial_init (void)

serial_init

[cpp] view plain copy
  1. #if !defined(CONFIG_SERIAL_MULTI)  
  2. int serial_init (void)  
  3. {  
  4.     int clock_divisor;  
  5.   
  6. #ifdef CFG_NS87308  
  7.     initialise_ns87308();  
  8. #endif  
  9.   
  10. #ifdef CFG_NS16550_COM1  
  11.     clock_divisor = calc_divisor(serial_ports[0]);  
  12.     NS16550_init(serial_ports[0], clock_divisor);  
  13. #endif  
  14. #ifdef CFG_NS16550_COM2  
  15.     clock_divisor = calc_divisor(serial_ports[1]);  
  16.     NS16550_init(serial_ports[1], clock_divisor);  
  17. #endif  
  18. #ifdef CFG_NS16550_COM3  
  19.     clock_divisor = calc_divisor(serial_ports[2]);  
  20.     NS16550_init(serial_ports[2], clock_divisor);  
  21. #endif  
  22. #ifdef CFG_NS16550_COM4  
  23.     clock_divisor = calc_divisor(serial_ports[3]);  
  24.     NS16550_init(serial_ports[3], clock_divisor);  
  25. #endif  
  26.   
  27.     return (0);  
  28. }  
  29. #endif  

 \uboot\common\console.c
 int console_init_f (void)

console_init_f

[cpp] view plain copy
  1. int console_init_f (void)  
  2. {  
  3.     gd->have_console = 1;  
  4.   
  5. #ifdef CONFIG_SILENT_CONSOLE  
  6.     if (getenv("silent") != NULL)  
  7.         gd->flags |= GD_FLG_SILENT;  
  8. #endif  
  9.   
  10.     return (0);  
  11. }  

 \uboot\common\cmd_nvedit.c 
    char *getenv (char *name)

getenv

[cpp] view plain copy
  1. char *getenv (char *name)  
  2. {  
  3.     int i, nxt;  
  4.   
  5.     WATCHDOG_RESET();  
  6.   
  7.     for (i=0; env_get_char(i) != '\0'; i=nxt+1) {  
  8.         int val;  
  9.   
  10.         for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {  
  11.             if (nxt >= CFG_ENV_SIZE) {  
  12.                 return (NULL);  
  13.             }  
  14.         }  
  15.         if ((val=envmatch((uchar *)name, i)) < 0)  
  16.             continue;  
  17.         return ((char *)env_get_addr(val));  
  18.     }  
  19.   
  20.     return (NULL);  
  21. }  

  \uboot\common\env_common.c (4 hits)
   uchar (*env_get_char)(int) = env_get_char_init;

  \uboot\common\env_common.c (3 hits)
    static uchar env_get_char_init (int index);
   uchar (*env_get_char)(int) = env_get_char_init;
    static uchar env_get_char_init (int index)

env_get_char_init

[cpp] view plain copy
  1. static uchar env_get_char_init (int index)  
  2. {  
  3.     uchar c;  
  4.   
  5.     /* if crc was bad, use the default environment */  
  6.     if (gd->env_valid)  
  7.     {  
  8.         c = env_get_char_spec(index);  
  9.     } else {  
  10.         c = default_environment[index];  
  11.     }  
  12.   
  13.     return (c);  
  14. }  



函数则是需要移植来实现,做clk初始化以及ddr初始化

从cpu_init_crit返回后,_start的工作就完成了,接下来就要调用_main,总结一下_start工作:

1 前面总结过的部分,初始化异常向量表,设置svc模式,关中断

2 配置cp15,初始化mmu cache tlb

3 板级初始化,pll memory初始化


二 _main

[cpp] view plain copy
  1. ENTRY(_main)    
  2.     
  3. /*  
  4.  * Set up initial C runtime environment and call board_init_f(0).  
  5.  */    
  6.     
  7. #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)    
  8.     ldr sp, =(CONFIG_SPL_STACK)    
  9. #else    
  10.     ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)    
  11. #endif    
  12.     bic sp, sp, #7  /* 8-byte alignment for ABI compliance */    
  13.     sub sp, sp, #GD_SIZE    /* allocate one GD above SP */    
  14.     bic sp, sp, #7  /* 8-byte alignment for ABI compliance */    
  15.     mov r9, sp      /* GD is above SP */    
  16.     mov r0, #0    
  17.     bl  board_init_f    
移植uboot先做一个最精简版本,很多配置选项都没有打开,比如fb mmc等硬件都默认不打开,只配置基本的ddr serial,这样先保证uboot能正常启动进入命令行,然后再去添加其他。

三 board_init_f

[cpp] view plain copy
  1. for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {    
  2.     if ((*init_fnc_ptr)() != 0) {    
  3.         hang ();    
  4.     }    
  5. }    

[cpp] view plain copy
  1. init_fnc_t *init_sequence[] = {    
  2.     arch_cpu_init,      /* basic arch cpu dependent setup */    
  3.     mark_bootstage,    
  4. #ifdef CONFIG_OF_CONTROL    
  5.     fdtdec_check_fdt,    
  6. #endif    
  7. #if defined(CONFIG_BOARD_EARLY_INIT_F)    
  8.     board_early_init_f,    
  9. #endif    
  10.     timer_init,     /* initialize timer */    
  11. #ifdef CONFIG_BOARD_POSTCLK_INIT    
  12.     board_postclk_init,    
  13. #endif    
  14. #ifdef CONFIG_FSL_ESDHC    
  15.     get_clocks,    
  16. #endif    
  17.     env_init,       /* initialize environment */    
  18.     init_baudrate,      /* initialze baudrate settings */    
  19.     serial_init,        /* serial communications setup */    
  20.     console_init_f,     /* stage 1 init of console */    
  21.     display_banner,     /* say that we are here */    
  22.     print_cpuinfo,      /* display cpu info (and speed) */    
  23. #if defined(CONFIG_DISPLAY_BOARDINFO)    
  24.     checkboard,     /* display board info */    
  25. #endif    
  26. #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)    
  27.     init_func_i2c,    
  28. #endif    
  29.     dram_init,      /* configure available RAM banks */    
  30.     NULL,    
  31. };    

五 relocate_code

七 board_init_r

可以看出,对于serial,uboot实现了一个2级初始化:

stage 1,仅初始化default console serial,printf到puts后会直接调用特定串口的puts函数,实现打印

stage 2,将所有serial注册为stdio_device,并挑出指定调试串口作为stdio_devices的stdout stdin stderr。printf到puts后再到全局stdio_devices中找到对应stdio_device,调用stdio-device的puts,最终调用特定serial的puts,实现打印。

区分这2个stage,是利用gd的flag,GD_FLG_DEVINIT。


[cpp] view plain copy
  1. 在G870中,C版的SDRAM为128MB(DDR2),E版的SDRAM为64MB(MDDR),它们在系统存储空间的基地址都为0x8000_0000,具体见iMAX25RM的数据手册:  
  2.   
  3.             在uboot中,我们必须设置好这些参数,主要是基地址和SDRAM的大小等。这里主要采用到了uboot的一个全局的结构体变量: bd_t : board info数据结构定义,位于文件 include/asm-arm/u-boot.h。主要是用来保存板子参数。  
  4.   
  5. typedef struct bd_info {  
  6. int                                    bi_baudrate;        /* serial console baudrate    串口波特率 */  
  7. unsigned long                     bi_ip_addr;         /* IPAddress    IP 地址 */  
  8. unsignedchar                     bi_enetaddr[6];     /*Ethernet adress    MAC地址*/  
  9. structenvironment_s       *bi_env;                //结构体变量定义见46行  
  10. ulong                                 bi_arch_number;   /* uniqueid for this board    板子的id*/  
  11. ulong                                 bi_boot_params;   /*where this board expects params 启动参数*/  
  12. struct     /* RAM configuration    RAM 配置*/  
  13. {  
  14. ulong start;  
  15. ulong size;  
  16. }    bi_dram[CONFIG_NR_DRAM_BANKS];  
  17. }bd_t;  
  18.   
  19.        其中红色部分为关于RAM的配置,初始化为:  
  20. int dram_init(void)  
  21. {  
  22. #ifdef CONFIG_MX25_MDDR  
  23.     gd->bd->bi_dram[0].start = PHYS_SDRAM_1;  // PHYS_SDRAM_1为0x8000_0000  
  24.     gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;  
  25. #else  
  26.     gd->bd->bi_dram[0].start = PHYS_SDRAM_1;  
  27.     gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;  
  28.   
  29. if(CONFIG_NR_DRAM_BANKS == 2)  // 其中CONFIG_NR_DRAM_BANKS = 1  ,因为只有一个BANKS  
  30. {  
  31.     gd->bd->bi_dram[1].start = PHYS_SDRAM_2;  
  32.     gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;  
  33. }  
  34. #endif  
  35.     return 0;  
  36. }  
  37.   
  38.            这样,就设置好了RAM的参数。接下来就是设置SDRAM的控制寄存器了,这里不再介绍  


ddr配置过程


这部分是参考网上资料以及xilinx官网关于DDR部分的配置翻译过来的步骤,如有错误,请及时指正.

[cpp] view plain copy
  1.  1. 提供稳压电源给内存控制器和内存芯片,内存控制器必须保持CLE在低电平,此时就会提供稳压电源。注:当CKE引脚为低电平时,XDDR2SEL应该处于高电平  
  2.   
  3.   2. 依照时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_incbit-fields的值。配置的PhyControl0.ctrl_dll_on值为'1'以打开PHY DLL。  
  4.   
  5.   3. DQS Cleaning:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetcbit-fields位的值。  
  6.   
  7.   4. 配置PhyControl0.ctrl_start位的值为'1'  
  8.   
  9.   5. 配置ConControl,与此同时,auto refresh自动刷新计数器应该关闭  
  10.   
  11.   6. 配置MemControl,与此同时,所有的power down(休眠模式)应该闭关  
  12.   
  13.   7. 配置MemConfig0寄存器。如果有两组内存芯片(比如有8片DDR,这8片DDR是分别挂在Memory Port1和Memory Port2上),再配置MemConfig1寄存器。  
  14.   
  15.   8. 配置PrechConfig和PwrdnConfig寄存器  
  16.   
  17.   9. 依照内存的tAC参数配置TimingAref, TimingRow, TimingData和TimingPower寄存器  
  18.   
  19.   10. 如果需要QoS标准,配置QosControl0~15和QosConfig0~15r寄存器  
  20.   
  21.   11. 等待PhyStatus0.ctrl_locked位变为'1'。检查是否PHY DLL是否已锁  
  22.   
  23.   12. PHY DLL补偿在内存操作时由PVT(Process, Voltage and Temperature,处理器、电压和温度)变化引起的延迟量。但是,PHY DLL不能因某些可靠的内存操作而切断,除非是工作在低频率下。如果关闭PHY DLL,依照PhyStatus0.ctrl_lock_value[9:2]位的值正确配置PhyControl0.ctrl_force位的值来弥补延迟量(fix delay amount)。清除PhyControl0.ctrl_dll_on位的值来关闭PHY DLL。  
  24.   
  25.   13. 上电后,确定最小值为200us的稳定时钟是否发出  
  26.   
  27.   14. 使用DirectCmd寄存器发出一个NOP命令,保证CKE引脚为高电平  
  28. 15. 等最小400ns  
  29.   
  30.   16. 使用DirectCmd寄存器发出一个PALL命令  
  31.   
  32.   17. 使用DirectCmd寄存器发出一个EMRS2命令,program操作参数  
  33.   
  34.   18. 使用DirectCmd寄存器发出一个EMRS3命令,program操作参数  
  35.   
  36.   19. 使用DirectCmd寄存器发出一个EMRS命令来使能内存DLLs  
  37.   
  38.   20. 使用DirectCmd寄存器发出一个MRS命令,重启内存DLL  
  39.   
  40.   21. 使用DirectCmd寄存器发出一个PALL命令  
  41.   
  42.   22. 使用DirectCmd寄存器发出两个Auto Refresh(自动刷新)命令  
  43.   
  44.   23. 使用DirectCmd寄存器发出一个MRS命令,program操作参数,不要重启内存DLL  
  45.   
  46.   24. 等待最小200时钟周期  
  47.   
  48.   25. 使用DirectCmd寄存器发出一个EMRS命令给程序的运行参数。如果OCD校正(Off-Chip Driver,片外驱动调校)没有使用,改善一个EMRS命令去设置OCD校准的默认值。在此之后,发送一个EMRS指令去退出OCD校准模式,继续program操作参数  
  49.   
  50.   26. 如果有两组DDR芯片,重复14-25步配置chip1的内存,刚刚配置的是chip0,也就是第一组内存芯片  
  51.   
  52.   27. 配置ConControlto来打开自动刷新计数器  
  53.   
  54.   28. 如果需要power down(休眠)模式,配置MemControl寄存器.  
原创粉丝点击