继上篇文章介绍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
- reset:
- #if defined(CONFIG_COMCERTO_300)
- #ifndef CONFIG_SKIP_RELOCATE_UBOOT
-
-
-
-
-
- mov r0, pc
- ldr r2, =reset - TEXT_BASE + 8
- cmp r0, r2
-
- ldreq pc, =COMCERTO_CS2_BASE + rom_second_loc - TEXT_BASE
- #endif
- rom_second_loc:
-
-
-
- ldr r2, =COMCERTO_DECODER_CSE
- ldr r3, [r2]
- bic r3, #DECODER_CSE_ROM_REMAP_ENABLE
- strh r3, [r2]
- #endif
-
-
-
-
- mrs r0,cpsr
- bic r0,r0,#0x1f
- orr r0,r0,#0xd3
- msr cpsr,r0
-
- #ifdef CONFIG_OMAP2420H4
-
- adr r0, _start
- add r0, r0, #4
- mov r2, #64
- add r2, r0, r2
- mov r1, #SRAM_OFFSET0
- mov r3, #SRAM_OFFSET1
- add r1, r1, r3
- mov r3, #SRAM_OFFSET2
- add r1, r1, r3
- next:
- ldmia r0!, {r3-r10}
- stmia r1!, {r3-r10}
- cmp r0, r2
- bne next
- bl cpy_clk_code
- #endif
-
- #ifndef CONFIG_SKIP_LOWLEVEL_INIT
- bl cpu_init_crit
- #endif
-
- #ifndef CONFIG_SKIP_RELOCATE_UBOOT
- relocate:
- adr r0, _start
- ldr r1, _TEXT_BASE
- cmp r0, r1
- beq stack_setup
-
- ldr r2, _armboot_start
- ldr r3, _bss_start
- sub r2, r3, r2
- add r2, r0, r2
-
- copy_loop:
- ldmia r0!, {r3-r10}
- stmia r1!, {r3-r10}
- cmp r0, r2
- ble copy_loop
- #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
-
-
- stack_setup:
- ldr r0, _TEXT_BASE
- sub r0, r0, #CFG_MALLOC_LEN
- sub r0, r0, #CFG_GBL_DATA_SIZE
- #ifdef CONFIG_USE_IRQ
- sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
- #endif
- sub sp, r0, #12
-
- clear_bss:
- ldr r0, _bss_start
- ldr r1, _bss_end
- mov r2, #0x00000000
-
- clbss_l:str r2, [r0]
- add r0, r0, #4
- cmp r0, r1
- bne clbss_l
-
- ldr pc, _start_armboot
-
- _start_armboot: .word start_armboot
cpu_init_crit
- cpu_init_crit:
-
-
-
- mov r0, #0
- mcr p15, 0, r0, c7, c7, 0
- mcr p15, 0, r0, c8, c7, 0
-
-
-
-
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
- bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
- orr r0, r0, #0x00000002 @ set bit 2 (A) Align
- orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
- orr r0, r0, #0x00400000 @ set bit 22 (U)
- mcr p15, 0, r0, c1, c0, 0
-
-
-
-
-
- mov ip, lr
- bl lowlevel_init
- mov lr, ip
- mov pc, lr
cpu_init_crit调用的lowlevel_init函数是与特定开发板相关的初始化函数,在这个函数里会做一些pll初始化,如果不是从mem启动,则会做memory初始化,方便后续拷贝到mem中运行。lowlevel_init
- lowlevel_init:
- ldr sp, TMP_STACK
-
- stmdb sp!, {ip, lr}
- bl bsp_init
- ldmia sp!, {ip, pc}
-
-
- .ltorg
- TMP_STACK:
- .word CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET
-
- #define CFG_INIT_RAM_ADDR ARAM_MEMORY_PHY
- #define CFG_INIT_SP_OFFSET 0x1000
-
- #define ARAM_MEMORY_PHY 0x0A000000
bsp_init
- void bsp_init(void)
- {
- comcerto300_init();
- comcerto300_pll_set_clocks(CFG_ARM_CLOCK, CFG_HZ_CLOCK, CFG_SPU_CLOCK);
-
-
- writel(0xD2DE, COMCERTO_SDC_SDRAM_CFG1);
- writel(0x0820, COMCERTO_SDC_SDRAM_REFRESH);
- writel(0x682B, COMCERTO_SDC_SDRAM_POWERON);
- writel(0x92CA, COMCERTO_SDC_SDRAM_CFG2);
-
-
- comcerto300_set_cs_type(0, 1);
- comcerto300_set_cs_region(0, PHYS_SDRAM, PHYS_SDRAM_SIZE);
- comcerto300_set_cse(0, 1);
-
- icache_enable();
- }
\uboot\lib_arm\board.c (1 hit) void start_armboot (void)start_armboot
- void start_armboot (void)
- {
- init_fnc_t **init_fnc_ptr;
- char *s;
- #ifndef CFG_NO_FLASH
- ulong size;
- #endif
- #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
- unsigned long addr;
- #endif
-
-
- gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
-
- __asm__ __volatile__("": : :"memory");
-
- memset ((void*)gd, 0, sizeof (gd_t));
- gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
- memset (gd->bd, 0, sizeof (bd_t));
-
- monitor_flash_len = _bss_start - _armboot_start;
-
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
- if ((*init_fnc_ptr)() != 0) {
- hang ();
- }
- }
-
- #ifndef CFG_NO_FLASH
-
- size = flash_init ();
- display_flash_config (size);
- #endif /* CFG_NO_FLASH */
-
- #ifdef CONFIG_VFD
- # ifndef PAGE_SIZE
- # define PAGE_SIZE 4096
- # endif
-
-
-
-
- addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
- size = vfd_setmem (addr);
- gd->fb_base = addr;
- #endif /* CONFIG_VFD */
-
- #ifdef CONFIG_LCD
- # ifndef PAGE_SIZE
- # define PAGE_SIZE 4096
- # endif
-
-
-
-
- addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
- size = lcd_setmem (addr);
- gd->fb_base = addr;
- #endif /* CONFIG_LCD */
-
-
- mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
-
- #if (CONFIG_COMMANDS & CFG_CMD_NAND)
- puts ("NAND: ");
- nand_init();
- #endif
-
- #ifdef CONFIG_HAS_DATAFLASH
- AT91F_DataflashInit();
- dataflash_print_info();
- #endif
-
-
- env_relocate ();
-
- #ifdef CONFIG_VFD
-
- drv_vfd_init();
- #endif /* CONFIG_VFD */
-
-
- gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
-
-
- {
- int i;
- ulong reg;
- char *s, *e;
- char tmp[64];
-
- i = getenv_r ("ethaddr", tmp, sizeof (tmp));
- s = (i > 0) ? tmp : NULL;
-
- for (reg = 0; reg < 6; ++reg) {
- gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
- if (s)
- s = (*e) ? e + 1 : e;
- }
-
- #ifdef CONFIG_HAS_ETH1
- i = getenv_r ("eth1addr", tmp, sizeof (tmp));
- s = (i > 0) ? tmp : NULL;
-
- for (reg = 0; reg < 6; ++reg) {
- gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
- if (s)
- s = (*e) ? e + 1 : e;
- }
- #endif
- }
-
- devices_init ();
-
- #ifdef CONFIG_CMC_PU2
- load_sernum_ethaddr ();
- #endif /* CONFIG_CMC_PU2 */
-
- jumptable_init ();
-
- console_init_r ();
-
- #if defined(CONFIG_MISC_INIT_R)
-
- misc_init_r ();
- #endif
-
-
- enable_interrupts ();
-
-
- #ifdef CONFIG_DRIVER_CS8900
- cs8900_get_enetaddr (gd->bd->bi_enetaddr);
- #endif
-
- #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
- if (getenv ("ethaddr")) {
- smc_set_mac_addr(gd->bd->bi_enetaddr);
- }
- #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
-
-
- if ((s = getenv ("loadaddr")) != NULL) {
- load_addr = simple_strtoul (s, NULL, 16);
- }
- #if (CONFIG_COMMANDS & CFG_CMD_NET)
- if ((s = getenv ("bootfile")) != NULL) {
- copy_filename (BootFile, s, sizeof (BootFile));
- }
- #endif /* CFG_CMD_NET */
-
- #ifdef BOARD_LATE_INIT
- board_late_init ();
- #endif
- #if (CONFIG_COMMANDS & CFG_CMD_NET)
- #if defined(CONFIG_NET_MULTI)
- puts ("Net: ");
- #endif
- eth_initialize(gd->bd);
- #endif
-
- for (;;) {
- main_loop ();
- }
-
-
- }
init_sequence
- init_fnc_t *init_sequence[] = {
- cpu_init,
- board_init,
- interrupt_init,
- env_init,
- init_baudrate,
- serial_init,
- console_init_f,
- display_banner,
- #if defined(CONFIG_DISPLAY_CPUINFO)
- print_cpuinfo,
- #endif
- #if defined(CONFIG_DISPLAY_BOARDINFO)
- checkboard,
- #endif
- dram_init,
- display_dram_config,
- NULL,
- };
display_banner是第一条打印语句
\uboot\cpu\arm1136\cpu.c (1 hit)
int cpu_init (void)
cpu_init
- int cpu_init (void)
- {
-
-
-
- #ifdef CONFIG_USE_IRQ
- IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
- FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
- #endif
- return 0;
- }
\uboot\board\xilinx\zynq\board.c int board_init(void)board_init
- static void nor_init(void)
- {
- u32 cs1_base = PHYS_FLASH2, fcs_base = PHYS_FLASH1;
- u32 cs1_size = 64*1024*1024, fcs_size = 1*1024*1024;
- u32 cs_nor8=2, cs_nor16=1;
-
-
-
-
-
-
-
-
-
-
-
-
-
- if ((readl(COMCERTO_GPIO_SYSTEM_CONFIG) & 2) != 0 && (readl(COMCERTO_GPIO_INPUT) & 0xE0) == 0x20) {
- u32 temp;
-
-
- temp = cs1_base, cs1_base = fcs_base, fcs_base = temp;
- temp = cs1_size, cs1_size = fcs_size, fcs_size = temp;
- temp = cs_nor8, cs_nor8 = cs_nor16, cs_nor16 = temp;
- }
-
- comcerto300_uexp_cfg_cs(cs_nor8, 0x0090, 0x0095, 0x0301);
- comcerto300_uexp_cfg_cs(cs_nor16, 0x0910, 0x0895, 0x0820);
-
- comcerto300_set_cs_region(1, cs1_base, cs1_size);
- comcerto300_set_fcs(1, 2, fcs_base, fcs_size);
-
- comcerto300_set_cse(1, 1);
- comcerto300_set_cse(2, 1);
- }
-
- int board_init(void)
- {
-
- gpio_direction_output(CFG_GPIO_OUT_PERIPHERAL_RESET, 0);
- udelay(100);
- gpio_set_value(CFG_GPIO_OUT_PERIPHERAL_RESET, 1);
-
-
-
-
- nor_init();
-
-
- comcerto300_uexp_cfg_cs(3, 0xC910, 0x08A5, 0x083A);
- comcerto300_set_cse(3, 1);
-
-
- comcerto300_uexp_cfg_cs(4, 0x1106, 0x08A5, 0x083A);
- comcerto300_set_cse(4, 1);
-
-
- comcerto300_uexp_cfg_cs(5, 0x2108, 0x0895, 0x0820);
- comcerto300_set_cse(5, 1);
- gpio_direction_input(CFG_GPIO_IN_NAND_BR);
-
- #if defined(CONFIG_TDM) || defined(CONFIG_TSI_MT90869)
- comcerto300_ntg_8mhz_init();
- #endif
-
- #if (CONFIG_COMMANDS & CFG_CMD_SPI)
- spi_hw_init();
- #endif
-
- #ifdef CONFIG_TSI_MT90869
- udelay(10*1000);
- tsi_hw_init((void*) COMCERTO_CS3_BASE);
- #endif
-
- return 0;
- }
-
- int dram_init(void)
- {
- gd->bd->bi_dram[0].start = PHYS_SDRAM;
- gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE;
-
- return 0;
- }
\ubootarch\arm\cpu\armv7\zynq\ interrupt_ini.c int interrupt_init(void)interrupt_init
- int interrupt_init(void)
- {
- writel(TIMER_LOAD_VAL, COMCERTO_TIMER0_HIGH_BOUND);
-
- lastinc = 0;
- ts_count = 0;
- ts_usec = 0;
-
- return 0;
- }
\ubootarch\arm\cpu\armv7\zynq\interrupts.c
int interrupt_init (void)
-
- int interrupt_init (void)
- {
- int32_t val;
-
-
- *((int32_t *) (CFG_TIMERBASE + TLDR)) = TIMER_LOAD_VAL;
- val = (CFG_PVT << 2) | BIT5 | BIT1 | BIT0;
- *((int32_t *) (CFG_TIMERBASE + TCLR)) = val;
-
- reset_timer_masked();
-
- return(0);
- }
\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
- int env_init(void)
- {
- #if defined(ENV_IS_EMBEDDED)
- ulong total;
- int crc1_ok = 0, crc2_ok = 0;
- env_t *tmp_env1, *tmp_env2;
-
- total = CFG_ENV_SIZE;
-
- tmp_env1 = env_ptr;
- tmp_env2 = (env_t *)((ulong)env_ptr + CFG_ENV_SIZE);
-
- crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
- crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
-
- if (!crc1_ok && !crc2_ok)
- gd->env_valid = 0;
- else if(crc1_ok && !crc2_ok)
- gd->env_valid = 1;
- else if(!crc1_ok && crc2_ok)
- gd->env_valid = 2;
- else {
-
- if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
- gd->env_valid = 2;
- else if(tmp_env2->flags == 255 && tmp_env1->flags == 0)
- gd->env_valid = 1;
- else if(tmp_env1->flags > tmp_env2->flags)
- gd->env_valid = 1;
- else if(tmp_env2->flags > tmp_env1->flags)
- gd->env_valid = 2;
- else
- gd->env_valid = 1;
- }
-
- if (gd->env_valid == 1)
- env_ptr = tmp_env1;
- else if (gd->env_valid == 2)
- env_ptr = tmp_env2;
- #else /* ENV_IS_EMBEDDED */
- gd->env_addr = (ulong)&default_environment[0];
- gd->env_valid = 1;
- #endif /* ENV_IS_EMBEDDED */
-
- return (0);
- }
\uboot\lib_arm\board.c (2 hits) static int init_baudrate (void)init_baudrate
- static int init_baudrate (void)
- {
- char tmp[64];
- int i = getenv_r ("baudrate", tmp, sizeof (tmp));
- gd->bd->bi_baudrate = gd->baudrate = (i > 0)
- ? (int) simple_strtoul (tmp, NULL, 10)
- : CONFIG_BAUDRATE;
-
- return (0);
- }
\uboot\common\serial.c (1 hit) int serial_init (void)serial_init
- int serial_init (void)
- {
- if (!(gd->flags & GD_FLG_RELOC) || !serial_current) {
- struct serial_device *dev = default_serial_console ();
-
- return dev->init ();
- }
-
- return serial_current->init ();
- }
\uboot\common\serial.c (8 hits) struct serial_device *default_serial_console (void)default_serial_console
- #ifndef CONFIG_LWMON
- struct serial_device *default_serial_console (void)
- {
- #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2)
- return &serial_smc_device;
- #elif defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \
- || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
- return &serial_scc_device;
- #elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) \
- || defined(CONFIG_405EP) || defined(CONFIG_MPC5xxx)
- #if defined(CONFIG_CONS_INDEX) && defined(CFG_NS16550_SERIAL)
- #if (CONFIG_CONS_INDEX==1)
- return &eserial1_device;
- #elif (CONFIG_CONS_INDEX==2)
- return &eserial2_device;
- #elif (CONFIG_CONS_INDEX==3)
- return &eserial3_device;
- #elif (CONFIG_CONS_INDEX==4)
- return &eserial4_device;
- #else
- #error "Bad CONFIG_CONS_INDEX."
- #endif
- #elif defined(CONFIG_UART1_CONSOLE)
- return &serial1_device;
- #else
- return &serial0_device;
- #endif
- #else
- #error No default console
- #endif
- }
- #endif
\uboot\include\serial.h (11 hits) struct serial_device {struct serial_device
- struct serial_device {
- char name[NAMESIZE];
- char ctlr[CTLRSIZE];
-
- int (*init) (void);
- void (*setbrg) (void);
- int (*getc) (void);
- int (*tstc) (void);
- void (*putc) (const char c);
- void (*puts) (const char *s);
-
- struct serial_device *next;
- };
\uboot\drivers\serial.c
int serial_init (void)
serial_init
- #if !defined(CONFIG_SERIAL_MULTI)
- int serial_init (void)
- {
- int clock_divisor;
-
- #ifdef CFG_NS87308
- initialise_ns87308();
- #endif
-
- #ifdef CFG_NS16550_COM1
- clock_divisor = calc_divisor(serial_ports[0]);
- NS16550_init(serial_ports[0], clock_divisor);
- #endif
- #ifdef CFG_NS16550_COM2
- clock_divisor = calc_divisor(serial_ports[1]);
- NS16550_init(serial_ports[1], clock_divisor);
- #endif
- #ifdef CFG_NS16550_COM3
- clock_divisor = calc_divisor(serial_ports[2]);
- NS16550_init(serial_ports[2], clock_divisor);
- #endif
- #ifdef CFG_NS16550_COM4
- clock_divisor = calc_divisor(serial_ports[3]);
- NS16550_init(serial_ports[3], clock_divisor);
- #endif
-
- return (0);
- }
- #endif
\uboot\common\console.c int console_init_f (void)console_init_f
- int console_init_f (void)
- {
- gd->have_console = 1;
-
- #ifdef CONFIG_SILENT_CONSOLE
- if (getenv("silent") != NULL)
- gd->flags |= GD_FLG_SILENT;
- #endif
-
- return (0);
- }
\uboot\common\cmd_nvedit.c char *getenv (char *name)getenv
- char *getenv (char *name)
- {
- int i, nxt;
-
- WATCHDOG_RESET();
-
- for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
- int val;
-
- for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {
- if (nxt >= CFG_ENV_SIZE) {
- return (NULL);
- }
- }
- if ((val=envmatch((uchar *)name, i)) < 0)
- continue;
- return ((char *)env_get_addr(val));
- }
-
- return (NULL);
- }
\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
- static uchar env_get_char_init (int index)
- {
- uchar c;
-
-
- if (gd->env_valid)
- {
- c = env_get_char_spec(index);
- } else {
- c = default_environment[index];
- }
-
- return (c);
- }
函数则是需要移植来实现,做clk初始化以及ddr初始化
从cpu_init_crit返回后,_start的工作就完成了,接下来就要调用_main,总结一下_start工作:
1 前面总结过的部分,初始化异常向量表,设置svc模式,关中断
2 配置cp15,初始化mmu cache tlb
3 板级初始化,pll memory初始化
二 _main
- ENTRY(_main)
-
-
-
-
-
- #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
- ldr sp, =(CONFIG_SPL_STACK)
- #else
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- #endif
- bic sp, sp, #7
- sub sp, sp, #GD_SIZE
- bic sp, sp, #7
- mov r9, sp
- mov r0, #0
- bl board_init_f
移植uboot先做一个最精简版本,很多配置选项都没有打开,比如fb mmc等硬件都默认不打开,只配置基本的ddr serial,这样先保证uboot能正常启动进入命令行,然后再去添加其他。三 board_init_f
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
- if ((*init_fnc_ptr)() != 0) {
- hang ();
- }
- }
- init_fnc_t *init_sequence[] = {
- arch_cpu_init,
- mark_bootstage,
- #ifdef CONFIG_OF_CONTROL
- fdtdec_check_fdt,
- #endif
- #if defined(CONFIG_BOARD_EARLY_INIT_F)
- board_early_init_f,
- #endif
- timer_init,
- #ifdef CONFIG_BOARD_POSTCLK_INIT
- board_postclk_init,
- #endif
- #ifdef CONFIG_FSL_ESDHC
- get_clocks,
- #endif
- env_init,
- init_baudrate,
- serial_init,
- console_init_f,
- display_banner,
- print_cpuinfo,
- #if defined(CONFIG_DISPLAY_BOARDINFO)
- checkboard,
- #endif
- #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
- init_func_i2c,
- #endif
- dram_init,
- NULL,
- };
五 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。
- 在G870中,C版的SDRAM为128MB(DDR2),E版的SDRAM为64MB(MDDR),它们在系统存储空间的基地址都为0x8000_0000,具体见iMAX25RM的数据手册:
-
- 在uboot中,我们必须设置好这些参数,主要是基地址和SDRAM的大小等。这里主要采用到了uboot的一个全局的结构体变量: bd_t : board info数据结构定义,位于文件 include/asm-arm/u-boot.h。主要是用来保存板子参数。
-
- typedef struct bd_info {
- int bi_baudrate;
- unsigned long bi_ip_addr;
- unsignedchar bi_enetaddr[6];
- structenvironment_s *bi_env;
- ulong bi_arch_number;
- ulong bi_boot_params;
- struct
- {
- ulong start;
- ulong size;
- } bi_dram[CONFIG_NR_DRAM_BANKS];
- }bd_t;
-
- 其中红色部分为关于RAM的配置,初始化为:
- int dram_init(void)
- {
- #ifdef CONFIG_MX25_MDDR
- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
- #else
- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
-
- if(CONFIG_NR_DRAM_BANKS == 2)
- {
- gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
- gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
- }
- #endif
- return 0;
- }
-
- 这样,就设置好了RAM的参数。接下来就是设置SDRAM的控制寄存器了,这里不再介绍
ddr配置过程
这部分是参考网上资料以及xilinx官网关于DDR部分的配置翻译过来的步骤,如有错误,请及时指正.
- 1. 提供稳压电源给内存控制器和内存芯片,内存控制器必须保持CLE在低电平,此时就会提供稳压电源。注:当CKE引脚为低电平时,XDDR2SEL应该处于高电平
-
- 2. 依照时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_incbit-fields的值。配置的PhyControl0.ctrl_dll_on值为'1'以打开PHY DLL。
-
- 3. DQS Cleaning:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetcbit-fields位的值。
-
- 4. 配置PhyControl0.ctrl_start位的值为'1'
-
- 5. 配置ConControl,与此同时,auto refresh自动刷新计数器应该关闭
-
- 6. 配置MemControl,与此同时,所有的power down(休眠模式)应该闭关
-
- 7. 配置MemConfig0寄存器。如果有两组内存芯片(比如有8片DDR,这8片DDR是分别挂在Memory Port1和Memory Port2上),再配置MemConfig1寄存器。
-
- 8. 配置PrechConfig和PwrdnConfig寄存器
-
- 9. 依照内存的tAC参数配置TimingAref, TimingRow, TimingData和TimingPower寄存器
-
- 10. 如果需要QoS标准,配置QosControl0~15和QosConfig0~15r寄存器
-
- 11. 等待PhyStatus0.ctrl_locked位变为'1'。检查是否PHY DLL是否已锁
-
- 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。
-
- 13. 上电后,确定最小值为200us的稳定时钟是否发出
-
- 14. 使用DirectCmd寄存器发出一个NOP命令,保证CKE引脚为高电平
- 15. 等最小400ns
-
- 16. 使用DirectCmd寄存器发出一个PALL命令
-
- 17. 使用DirectCmd寄存器发出一个EMRS2命令,program操作参数
-
- 18. 使用DirectCmd寄存器发出一个EMRS3命令,program操作参数
-
- 19. 使用DirectCmd寄存器发出一个EMRS命令来使能内存DLLs
-
- 20. 使用DirectCmd寄存器发出一个MRS命令,重启内存DLL
-
- 21. 使用DirectCmd寄存器发出一个PALL命令
-
- 22. 使用DirectCmd寄存器发出两个Auto Refresh(自动刷新)命令
-
- 23. 使用DirectCmd寄存器发出一个MRS命令,program操作参数,不要重启内存DLL
-
- 24. 等待最小200时钟周期
-
- 25. 使用DirectCmd寄存器发出一个EMRS命令给程序的运行参数。如果OCD校正(Off-Chip Driver,片外驱动调校)没有使用,改善一个EMRS命令去设置OCD校准的默认值。在此之后,发送一个EMRS指令去退出OCD校准模式,继续program操作参数
-
- 26. 如果有两组DDR芯片,重复14-25步配置chip1的内存,刚刚配置的是chip0,也就是第一组内存芯片
-
- 27. 配置ConControlto来打开自动刷新计数器
-
- 28. 如果需要power down(休眠)模式,配置MemControl寄存器.