继上篇文章介绍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
- /* If booting from external boot ROM we are at address 0x00000000 and
- * must jump to CS2 range 0x11000000 before disabling the low
- * memory aliasing. If booting from IBR we are already at high address
- * and there is nothing to do.
- */
- 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:
- /* we are running in CS2 range, it's safe to disable ROM remapping,
- * just keep CS2 enabled for now
- */
- ldr r2, =COMCERTO_DECODER_CSE
- ldr r3, [r2]
- bic r3, #DECODER_CSE_ROM_REMAP_ENABLE
- strh r3, [r2]
- #endif
- /*
- * set the cpu to SVC32 mode
- */
- mrs r0,cpsr
- bic r0,r0,#0x1f
- orr r0,r0,#0xd3
- msr cpsr,r0
- #ifdef CONFIG_OMAP2420H4
- /* Copy vectors to mask ROM indirect addr */
- adr r0, _start /* r0 <- current position of code */
- add r0, r0, #4 /* skip reset vector */
- mov r2, #64 /* r2 <- size to copy */
- add r2, r0, r2 /* r2 <- source end address */
- mov r1, #SRAM_OFFSET0 /* build vect addr */
- mov r3, #SRAM_OFFSET1
- add r1, r1, r3
- mov r3, #SRAM_OFFSET2
- add r1, r1, r3
- next:
- ldmia r0!, {r3-r10} /* copy from source address [r0] */
- stmia r1!, {r3-r10} /* copy to target address [r1] */
- cmp r0, r2 /* until source end address [r2] */
- bne next /* loop until equal */
- bl cpy_clk_code /* put dpll adjust code behind vectors */
- #endif
- /* the mask ROM code should have PLL and others stable */
- #ifndef CONFIG_SKIP_LOWLEVEL_INIT
- bl cpu_init_crit
- #endif
- #ifndef CONFIG_SKIP_RELOCATE_UBOOT
- relocate: /* relocate U-Boot to RAM */
- adr r0, _start /* r0 <- current position of code */
- ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
- cmp r0, r1 /* don't reloc during debug */
- beq stack_setup
- ldr r2, _armboot_start
- ldr r3, _bss_start
- sub r2, r3, r2 /* r2 <- size of armboot */
- add r2, r0, r2 /* r2 <- source end address */
- copy_loop:
- ldmia r0!, {r3-r10} /* copy from source address [r0] */
- stmia r1!, {r3-r10} /* copy to target address [r1] */
- cmp r0, r2 /* until source end addreee [r2] */
- ble copy_loop
- #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
- /* Set up the stack */
- stack_setup:
- ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
- sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
- sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
- #ifdef CONFIG_USE_IRQ
- sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
- #endif
- sub sp, r0, #12 /* leave 3 words for abort-stack */
- clear_bss:
- ldr r0, _bss_start /* find start of bss segment */
- ldr r1, _bss_end /* stop here */
- mov r2, #0x00000000 /* clear */
- clbss_l:str r2, [r0] /* clear loop... */
- 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:
- /*
- * flush v4 I/D caches
- */
- mov r0, #0
- mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
- mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
- /*
- * disable MMU stuff and caches
- */
- 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
- /*
- * Jump to board specific initialization... The Mask ROM will have already initialized
- * basic memory. Go here to bump up clock rate and handle wake up conditions.
- */
- mov ip, lr /* persevere link reg across call */
- bl lowlevel_init /* go setup pll,mux,memory */
- mov lr, ip /* restore link */
- mov pc, lr /* back to my caller */
lowlevel_init
- lowlevel_init:
- ldr sp, TMP_STACK /* set up a temporary stack */
- stmdb sp!, {ip, lr}
- bl bsp_init /* go setup pll, memory */
- ldmia sp!, {ip, pc} /* restore registers and return to caller */
- /* the literal pools origin */
- .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);
- /* setup SDRAM controller, values are design specific */
- writel(0xD2DE, COMCERTO_SDC_SDRAM_CFG1);
- writel(0x0820, COMCERTO_SDC_SDRAM_REFRESH);
- writel(0x682B, COMCERTO_SDC_SDRAM_POWERON);
- writel(0x92CA, COMCERTO_SDC_SDRAM_CFG2);
- /* setup SDRAM - it on CS0 only for C300EVM */
- comcerto300_set_cs_type(0, 1); /* allow access to SDRAM via CS0 */
- comcerto300_set_cs_region(0, PHYS_SDRAM, PHYS_SDRAM_SIZE); /* define memory region for CS0 */
- comcerto300_set_cse(0, 1); /* enable CS0 */
- icache_enable();
- }
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
- /* Pointer is writable since we allocated a register for it */
- gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
- /* compiler optimization barrier needed for GCC >= 3.4 */
- __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
- /* configure available FLASH banks */
- size = flash_init ();
- display_flash_config (size);
- #endif /* CFG_NO_FLASH */
- #ifdef CONFIG_VFD
- # ifndef PAGE_SIZE
- # define PAGE_SIZE 4096
- # endif
- /*
- * reserve memory for VFD display (always full pages)
- */
- /* bss_end is defined in the board-specific linker script */
- 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
- /*
- * reserve memory for LCD display (always full pages)
- */
- /* bss_end is defined in the board-specific linker script */
- addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
- size = lcd_setmem (addr);
- gd->fb_base = addr;
- #endif /* CONFIG_LCD */
- /* armboot_start is defined in the board-specific linker script */
- mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
- #if (CONFIG_COMMANDS & CFG_CMD_NAND)
- puts ("NAND: ");
- nand_init(); /* go init the NAND */
- #endif
- #ifdef CONFIG_HAS_DATAFLASH
- AT91F_DataflashInit();
- dataflash_print_info();
- #endif
- /* initialize environment */
- env_relocate ();
- #ifdef CONFIG_VFD
- /* must do this after the framebuffer is allocated */
- drv_vfd_init();
- #endif /* CONFIG_VFD */
- /* IP Address */
- gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
- /* MAC Address */
- {
- 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 (); /* get the devices list going. */
- #ifdef CONFIG_CMC_PU2
- load_sernum_ethaddr ();
- #endif /* CONFIG_CMC_PU2 */
- jumptable_init ();
- console_init_r (); /* fully init console as a device */
- #if defined(CONFIG_MISC_INIT_R)
- /* miscellaneous platform dependent initialisations */
- misc_init_r ();
- #endif
- /* enable exceptions */
- enable_interrupts ();
- /* Perform network card initialisation if necessary */
- #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 */
- /* Initialize from environment */
- 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
- /* main_loop() can return to retry autoboot, if so just run it again. */
- for (;;) {
- main_loop ();
- }
- /* NOTREACHED - no way out of command loop except booting */
- }
init_sequence
- init_fnc_t *init_sequence[] = {
- cpu_init, /* basic cpu dependent setup */
- board_init, /* basic board dependent setup */
- interrupt_init, /* set up exceptions */
- env_init, /* initialize environment */
- init_baudrate, /* initialze baudrate settings */
- serial_init, /* serial communications setup */
- console_init_f, /* stage 1 init of console */
- display_banner, /* say that we are here */
- #if defined(CONFIG_DISPLAY_CPUINFO)
- print_cpuinfo, /* display cpu info (and speed) */
- #endif
- #if defined(CONFIG_DISPLAY_BOARDINFO)
- checkboard, /* display board info */
- #endif
- dram_init, /* configure available RAM banks */
- display_dram_config,
- NULL,
- };
display_banner是第一条打印语句
\uboot\cpu\arm1136\cpu.c (1 hit)
int cpu_init (void)
cpu_init
- int cpu_init (void)
- {
- /*
- * setup up stacks if necessary
- */
- #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;
- /*
- * Supported types of boot from external flash:
- * 1. Direct boot from external NOR8 flash (CS2: NOR8, CS1: NOR16)
- * 2. Secondary boot via IBR from NOR8 (CS2: NOR8, CS1: NOR16)
- * 3. Secondary boot via IBR from NOR16 (CS2: NOR16, CS1: NOR8)
- *
- * To avoid messing with different types of flash at the one fixed
- * address (CS2 at 0x11000000) we use programmable FCS. CS1 is ok
- * since base address is not fixed. So, defaults are for the case 1)
- * and 2). If we detect case 3) we just swap default values.
- */
- if ((readl(COMCERTO_GPIO_SYSTEM_CONFIG) & 2) != 0 && (readl(COMCERTO_GPIO_INPUT) & 0xE0) == 0x20) {
- u32 temp;
- /* IBR NOR16 boot - map NOR8 on CS1, map NOR16 on CS2/FCS - just swap default cs stuff */
- 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)
- {
- /* reset on-board peripherals via GPIO line */
- gpio_direction_output(CFG_GPIO_OUT_PERIPHERAL_RESET, 0);
- udelay(100);
- gpio_set_value(CFG_GPIO_OUT_PERIPHERAL_RESET, 1);
- /* CS0 is used for SDRAM, see bsp_init() */
- /* CS1 and CS2 used for flash memories */
- nor_init();
- /* CS3 - TSI */
- comcerto300_uexp_cfg_cs(3, 0xC910, 0x08A5, 0x083A);
- comcerto300_set_cse(3, 1);
- /* CS4 - PLD */
- comcerto300_uexp_cfg_cs(4, 0x1106, 0x08A5, 0x083A);
- comcerto300_set_cse(4, 1);
- /* CS5 - NAND */
- comcerto300_uexp_cfg_cs(5, 0x2108, 0x0895, 0x0820);
- comcerto300_set_cse(5, 1);
- gpio_direction_input(CFG_GPIO_IN_NAND_BR); /* ready signal is connected to GPIO line */
- #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)
- /* nothing really to do with interrupts, just starts up a counter. */
- int interrupt_init (void)
- {
- int32_t val;
- /* Start the counter ticking up */
- *((int32_t *) (CFG_TIMERBASE + TLDR)) = TIMER_LOAD_VAL; /* reload value on overflow*/
- val = (CFG_PVT << 2) | BIT5 | BIT1 | BIT0; /* mask to enable timer*/
- *((int32_t *) (CFG_TIMERBASE + TCLR)) = val; /* start timer */
- reset_timer_masked(); /* init the timestamp and lastinc value */
- return(0);
- }
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 {
- /* both ok - check serial */
- 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 /* flags are equal - almost impossible */
- 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);
- }
static int init_baudrate (void)
init_baudrate
- static int init_baudrate (void)
- {
- char tmp[64]; /* long enough for environment variables */
- 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 crc was bad, use the default environment */
- 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)
- /*
- * Set up initial C runtime environment and call board_init_f(0).
- */
- #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 /* 8-byte alignment for ABI compliance */
- sub sp, sp, #GD_SIZE /* allocate one GD above SP */
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- mov r9, sp /* GD is above SP */
- mov r0, #0
- bl board_init_f
三 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, /* basic arch cpu dependent setup */
- mark_bootstage,
- #ifdef CONFIG_OF_CONTROL
- fdtdec_check_fdt,
- #endif
- #if defined(CONFIG_BOARD_EARLY_INIT_F)
- board_early_init_f,
- #endif
- timer_init, /* initialize timer */
- #ifdef CONFIG_BOARD_POSTCLK_INIT
- board_postclk_init,
- #endif
- #ifdef CONFIG_FSL_ESDHC
- get_clocks,
- #endif
- env_init, /* initialize environment */
- init_baudrate, /* initialze baudrate settings */
- serial_init, /* serial communications setup */
- console_init_f, /* stage 1 init of console */
- display_banner, /* say that we are here */
- print_cpuinfo, /* display cpu info (and speed) */
- #if defined(CONFIG_DISPLAY_BOARDINFO)
- checkboard, /* display board info */
- #endif
- #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
- init_func_i2c,
- #endif
- dram_init, /* configure available RAM banks */
- 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; /* serial console baudrate 串口波特率 */
- unsigned long bi_ip_addr; /* IPAddress IP 地址 */
- unsignedchar bi_enetaddr[6]; /*Ethernet adress MAC地址*/
- structenvironment_s *bi_env; //结构体变量定义见46行
- ulong bi_arch_number; /* uniqueid for this board 板子的id*/
- ulong bi_boot_params; /*where this board expects params 启动参数*/
- struct /* RAM configuration RAM 配置*/
- {
- 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; // PHYS_SDRAM_1为0x8000_0000
- 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) // 其中CONFIG_NR_DRAM_BANKS = 1 ,因为只有一个BANKS
- {
- 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寄存器.