2014.4版本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: #undef CONFIG_SKIP_RELOCATE_UBOOT
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 */
cpu_init_crit调用的lowlevel_init函数是与特定开发板相关的初始化函数,在这个函数里会做一些pll初始化,如果不是从mem启动,则会做memory初始化,方便后续拷贝到mem中运行。
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();
}
G:\sftp\c3001\c300\uboot\lib_arm\board.c (1 hit)
Line 243: 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是第一条打印语句
G:\sftp\c3001\c300\uboot\cpu\arm1136\cpu.c (1 hit)
Line 89: 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;
}
G:\sftp\c3001\c300\uboot\board\mindspeed\c300evm\board.c (1 hit)
Line 95: 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;
}
G:\sftp\c3001\c300\uboot\cpu\arm1136\comcerto\interrupts.c (1 hit)
Line 34: 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;
}
G:\sftp\c3001\c300\uboot\cpu\arm1136\interrupts.c (1 hit)
Line 187: 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);
}
G:\sftp\c3001\c300\uboot\common\env_flash.c (2 hits)
Line 99: int env_init(void)
Line 263: int env_init(void)
G:\sftp\c3001\c300\uboot\common\env_nand.c (1 hit)
Line 102: 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);
}
G:\sftp\c3001\c300\uboot\lib_arm\board.c (2 hits)
Line 126: 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);
}
G:\sftp\c3001\c300\uboot\common\serial.c (1 hit)
Line 162: 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 ();
}
G:\sftp\c3001\c300\uboot\common\serial.c (8 hits)
Line 36: 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
G:\sftp\c3001\c300\uboot\include\serial.h (11 hits)
Line 7: 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;
};
G:\sftp\c3001\c300\uboot\drivers\serial.c (1 hit)
Line 152: 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
G:\sftp\c3001\c300\uboot\common\console.c (1 hit)
Line 362: 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);
}
G:\sftp\c3001\c300\uboot\common\cmd_nvedit.c (1 hit)
Line 491: 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);
}
G:\sftp\c3001\c300\uboot\common\env_common.c (4 hits)
Line 60: uchar (*env_get_char)(int) = env_get_char_init;
G:\sftp\c3001\c300\uboot\common\env_common.c (3 hits)
Line 59: static uchar env_get_char_init (int index);
Line 60: uchar (*env_get_char)(int) = env_get_char_init;
Line 153: 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
移植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, /* 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配置过程
1. To provide stable power for controller and memory device, the controller must assert and hold CKE to a logic low level. Then apply stable clock. Note: XDDR2SEL should be High level to hold CKE to low.
2. Set the PhyControl0.ctrl_start_point and PhyControl0.ctrl_incbit-fields to correct value according to clock frequency. Set the PhyControl0.ctrl_dll_onbit-field to ‘1’ to turn on the PHY DLL.
3. DQS Cleaning: Set the PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetcbit-fields to correct value according to clock frequency and memory tAC parameters.
4. Set the PhyControl0.ctrl_start bit-field to ‘1’.
5. Set the ConControl. At this moment, an auto refresh counter should be off.
6. Set the MemControl. At this moment, all power down modes should be off.
7. Set the MemConfig0 register. If there are two external memory chips, set the MemConfig1 register.
8. Set the PrechConfigand PwrdnConfigregisters.
9. Set the TimingAref, TimingRow, TimingDataand TimingPower registers according to memory AC parameters.
10. If QoS scheme is required, set the QosControl0~15and QosConfig0~15registers.
11. Wait for thePhyStatus0.ctrl_lockedbit-fields to change to ‘1’. Check whether PHY DLL is locked.
12. PHY DLL compensates the changes of delay amountcaused by Process, Voltage and Temperature (PVT) variation during memory operation. Therefore, PHY DLL should not be off for reliable operation. It can be off except runs at low frequency. If off mode is used, set thePhyControl0.ctrl_forcebit-field to correct value according to thePhyStatus0.ctrl_lock_value[9:2]bit-field to fix delay amount. Clear the PhyControl0.ctrl_dll_on bit-field to turn off PHY DLL.
13. Confirm whether stable clock is issued minimum 200us after power on
14. Issue a NOPcommand using the DirectCmdregister to assert and to hold CKE to a logic high level.
15. Wait for minimum 400ns.
16. Issue a PALL command using the DirectCmd register.
17. Issue an EMRS2 command using the DirectCmd register to program the operating parameters.
18. Issue an EMRS3 command using the DirectCmd register to program the operating parameters.
19. Issue an EMRS command using the DirectCmd register to enable the memory DLLs.
20. Issue a MRS command using the DirectCmd register to reset the memory DLL.
21. Issue a PALL command using the DirectCmd register.
22. Issue two Auto Refreshcommands using the DirectCmd register.
23. Issue a MRS command using the DirectCmd register to program the operating parameters without resetting the memory DLL.
24. Wait for minimum 200 clock cycles.
25. Issue an EMRS command using the DirectCmd register to program the operating parameters. If OCD calibration is not used, issue an EMRS command to set OCD Calibration Default. After that, issue an EMRS command to exit OCD Calibration Mode and to program the operating parameters.
26. If there are two external memory chips, perform steps 14~25 for chip1 memory device.
27. Set the ConControlto turn on an auto refresh counter.
28. If power down modes is required, set the MemControl registers.
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寄存器.
---------------------
原文:https://blog.csdn.net/q123456789098/article/details/49582543