1, uboot启动的第一个阶段 :bootcode/btcode_vg/start.h
#ifdef CONFIG_NONO_COMPRESS
#define BOOT_ADDR 0xA0000000 // no compress
#else
#define BOOT_ADDR 0x80100000 //compress
#endif
// Using register: t6, t7 //wei add this code
#define IF_EQ(a,b,lab) or t6,zero,a;\
or t7,zero,b;\
beq t6,t7,lab;\
nop;
#define IF_NEQ(a,b,lab) or t6,zero,a;\
or t7,zero,b;\
bne t6,t7,lab;\
nop;
#define ADDR 0xA0380000
#define PATT0 0x5a0000a5
#define PATT1 0xA5A55A5A
#define PATT2 0x005AA500
#define PATT3 0xA5A55A5A
#define PATT4 0xAAAAAAAA
#define PATT5 0xffffffff
#define PATT6 0x00000000
#define PATT7 0x00000000
#define PATT8 0xffffffff
#define CLK_MANAGER 0xb8000010
#define DCR 0xb8001004
#define DRAM_DDR2 1
#define DRAM_DDR3 2
#define GET_BITVAL(v,bitpos,pat) ((v& ((unsigned int)pat<<bitpos))>>bitpos)
#define RANG1 1
#define RANG2 3
#define RANG3 7
#define RANG4 0xf
#define RANG5 0x1f
#define SYS_HW_STRAP (0xb8000000 +0x08)
#define SRAM_REG_SET_SIZE (0x10)
#define SRAM_REG_SET_NUM (4)
#define SRAM_REG_BASE_ADDR (0xB8004000)
#define C0SRAMSAR_REG_ADDR (SRAM_REG_BASE_ADDR + 0x0)
#define C0SRAMSSR_REG_ADDR (SRAM_REG_BASE_ADDR + 0x4)
#define C0SRAMSBR_REG_ADDR (SRAM_REG_BASE_ADDR + 0x8)
#define C1SRAMSAR_REG_ADDR (SRAM_REG_BASE_ADDR + 0x40)
#define C1SRAMSSR_REG_ADDR (SRAM_REG_BASE_ADDR + 0x44)
#define C1SRAMSBR_REG_ADDR (SRAM_REG_BASE_ADDR + 0x48)
#define SRAM_SEG_ENABLE (0x1)
#define SRAM_SIZE_256B (0x1)
#define SRAM_SIZE_512B (0x2)
#define SRAM_SIZE_1KB (0x3)
#define SRAM_SIZE_2KB (0x4)
#define SRAM_SIZE_4KB (0x5)
#define SRAM_SIZE_8KB (0x6)
#define SRAM_SIZE_16KB (0x7)
#define SRAM_SIZE_32KB (0x8)
#define SRAM_SIZE_64KB (0x9)
#define SRAM_SIZE_128KB (0xA)
#define SRAM_SIZE_256KB (0xB)
#define SRAM_SIZE_512KB (0xC)
#define SRAM_SIZE_1MB (0xD)
bootcode/btcode_vg/start.S
#include <asm/asm.h>
#include <regdef.h>
#include <asm/mipsregs.h>
#include "start.h"
#include "../autoconf.h"
#define CONFIG_CACHE_INIT
#define CONFIG_SYS_ROM_CACHE_BASE_ADDR 0x9FD00000
#define CONFIG_SYS_SRAM_CACHE_BASE_ADDR 0x9FE00000
#define CONFIG_SYS_ROM_NONCACHE_BASE_ADDR 0xBFD00000
#define CONFIG_SYS_SRAM_NONCACHE_BASE_ADDR 0xBFE00000
#define CONFIG_SYS_ROM_PHY_BASE_ADDR 0x1FD00000
#define CONFIG_SYS_SRAM_PHY_BASE_ADDR 0x1FE00000
#define CONFIG_SYS_INIT_SP_OFFSET 0x4000
/* cache */
#define INDEX_INVALIDATE_I 0x00
#define INDEX_WRITEBACK_INV_D 0x01
#define START_ADDR 0x80000000
#define CONFIG_SYS_CACHELINE_SIZE 32
#define _ICACHE_SIZE (64 * 1024)
#define _DCACHE_SIZE (32 * 1024)
.text
.set noreorder
.globl __start
__start:
j reset
nop
nop
reset:
nop
nop
nop
REG32_ANDOR(0xb8000010,~(1<<11),0);
nop
nop
nop
nop
REG32_W(0xb8000014, ((1<<8)|(1<<4))); //enable uart
nop
#ifndef CONFIG_DECREASE_BOOTSIZE
#if 1
jal uart_show //show boot msg
nop
#endif
#endif
/* Clear watch registers */
mtc0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
/* WP(Watch Pending), SW0/1 should be cleared */
mtc0 zero, CP0_CAUSE
mfc0 t0, CP0_STATUS
or t0, ST0_CU0 | 0x1f
xor t0, 0x1f
mtc0 t0, CP0_STATUS
.set noreorder
sll zero, 3 # ehb
/* Init Timer */
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
#ifdef CONFIG_CACHE_INIT
nop
li t7, 0xb8000008
lw t6, 0(t7)
and t6,t6,0x0F
li t7, 0x01
beq t6,t7, cache_init_end
nop
/* CONFIG0 register */
mfc0 t0, CP0_CONFIG
li t1,~CONF_CM_CMASK
and t0,t0,t1
ori t0,t0,CONF_CM_UNCACHED
mtc0 t0,CP0_CONFIG
/* processor ID */
mfc0 k1, C0_PRId
li t0, M_PRIdImp | M_PRIdCoID
and k1, t0
/* Initialize caches... */
la t9, sys_init_cache
jalr t9
nop
/* ... and enable them */
mfc0 t0, CP0_CONFIG
li t1,~CONF_CM_CMASK
and t0,t0,t1
ori t0,t0,CONF_CM_CACHABLE_NONCOHERENT
mtc0 t0,CP0_CONFIG
cache_init_end:
#endif
//------------------------------------------------
//============================================================================
//UART_WRITE('G');
#ifndef CONFIG_NAND_FLASH_BOOTING
/* Set up temporary stack */
/* spi flash do ddr init here */
li sp, (CONFIG_SYS_SRAM_CACHE_BASE_ADDR + CONFIG_SYS_INIT_SP_OFFSET - 0x20)
nop
jal start_c
#endif
nop
nop
//--------------------------------------------------------------------------------
flash2ram:
// Load to 80100000 for compress
// Load to 80000000 for non-compress
la k0, __boot_start
la k1, (__boot_end + 4)
la t1, BOOT_ADDR
1:
#if 0
jal SPI_show //show SPI msg
nop
#endif
lw t0, 0(k0)
nop
sw t0, 0(t1) //*(t1)=*(t0) t1+=4; t0+=4; t1=BOOT_ADDR, t0=__boot_start, run loop
nop
addu t1, 4
addu k0, 4
bne k1, k0, 1b
nop
// UART_PRINT_DELAY(SPI_done_msg);
/* flush dcache */
li a0, (START_ADDR+_DCACHE_SIZE)
li a1, START_ADDR
2:
cache INDEX_WRITEBACK_INV_D,0(a1)
nop
addu a1, CONFIG_SYS_CACHELINE_SIZE
bne a1,a0,2b
nop
/* invalid icache */
li a0, (START_ADDR+_ICACHE_SIZE)
li a1, START_ADDR
3:
cache INDEX_INVALIDATE_I,0(a1)
nop
addu a1,CONFIG_SYS_CACHELINE_SIZE
bne a1,a0,3b
nop
// Jump to booting
li k0, BOOT_ADDR
jr k0
nop
//all END
//--------------------------------------------------------------------------------
boot_msg: .ascii "\r\nBooting...\r\n\0"
SPI_done_msg: .ascii "\r\nSPI image move done ->Jump to DRAM\r\n\0"
SPI_msg: .ascii "\r\n.\0"
#endif
//==========================================================================
CPU上电 (0xBFCO0000)
↓
reset: 基本硬件初始化,CPU初始化
↓
缓存初始化,初始化DDR
↓
设置栈指针,从SPI Flash拷贝代码到DDR,刷新缓存
↓
jal start_c ← 调用第二阶段C代码
↓
(第二阶段代码执行DDR初始化等)
↓
返回后执行flash2ram, 更完整的外设初始化;
↓
从Flash复制到RAM
↓
跳转到RAM执行
bootcode\btcode_vg\start_c.c
void start_c(void)
{
EFUSE_DATA efuse_data;
u1Byte dram_type_idx, dram_freq_idx;
u4Byte strap_pin;
u4Byte dram_val, cpu_freq;
// (dram_type, dram_freq)
// 0,0 => DDR2 400 MHz
// 0,1 => DDR2 533 MHz
// 1,0 => DDR1 200 MHz
// 1,1 => DDR1 250 MHz
u4Byte dram_table[2][2] = {{400, 533}, {200, 250}};
//modify OCP_L to 0x000 1170mA
REG32(0xb8000260) = REG32(0xb8000260) & (~(1<<31));
REG32(0xb8000264) = REG32(0xb8000264) & (~3);
REG32(0xb80002c8) = ( REG32(0xb80002c8) & (~3)| 0x2 );
#ifdef CONFIG_RTL_8197F_VG
REG32(0xb800311c) = 0xa5600000; //disable watcdog
#endif
#ifdef CONFIG_ESD_SUPPORT
REG32(BSP_CDBR)=(BSP_DIVISOR) << BSP_DIVF_OFFSET;
REG32(BSP_TC0DATA) = (((BSP_SYS_CLK_RATE/BSP_DIVISOR)/HZ)) << 4;
REG32(0xb800311c)=0x00600000;
/*For DDR3 must , for DDR2 safe*/
#endif
#if defined(CONFIG_SW_8367R) || defined(CONFIG_SW_83XX)
REG32(BSP_PIN_MUX_SEL3) = (REG32(BSP_PIN_MUX_SEL3) & ~(3<<30)) | (0x3<<30);
REG32(BSP_PEFGH_CNR) &= (~(0x00000040));
REG32(BSP_PEFGH_DIR) |= (0x00000040);
REG32(BSP_PEFGH_DAT) &= (~(0x00000040));
#endif
_memctl_debug_printf("\n8197F Cstart\n");
timer_init();
strap_pin = REG32(REG_HW_STRAP);
cpu_freq = get_cpu_freq(strap_pin);
// dram_type: 0: DDR2, 1:DDR1
dram_type_idx = BIT_GET_STRAP_PIN_DRAM_TYPE_INV(strap_pin);
//printf("*pdram_type_idx:%d\n",*pdram_type_idx);
if ((strap_pin & BIT_STRAP_PIN_HW_DBG_DISABLE) == BIT_STRAP_PIN_HW_DBG_DISABLE) {
dram_freq_idx = BIT_GET_STRAP_PIN_DRAM_FEQ(strap_pin);
//printf("1111 *pdram_freq_idx:%d\n",*pdram_freq_idx);
} else { // HW_DBG_DISABLE == 0
dram_freq_idx = 0;
}
switch (REG32(0xB800000C) & 0x0F) {
case 0x06:
case 0x0C:
dram_val = 32;
break;
case 0x04:
case 0x0A:
dram_val = 64;
break;
case 0x05:
case 0x0B:
dram_val = 128;
break;
default:
#ifdef CONFIG_DRAM_SIZE
dram_val = CONFIG_DRAM_SIZE_IN_MB;
#else
//dram_val = 32;
// dram_val = REG32(0xB8000F00); // auto detect
dram_val = 0;
#endif
break;
}
REG32(0xB8000F00) = dram_val;
memset(&efuse_data, 0, sizeof(EFUSE_DATA));
#ifdef CONFIG_RTL_8197F_VG
rtl8197f_vg_calibration();
#endif
init_ram(strap_pin, dram_type_idx, dram_freq_idx, &efuse_data);
dram_val = REG32(0xB8000F00);
if (dram_type_idx == 0)
printf("\nDRAM Type: DDR2\n");
else
printf("\nDRAM Type: DDR1\n");
/*#ifdef CONFIG_CPU_1G_DDR2_533M
printf("\tDRAM frequency: 533MHz\n");
#elif defined(CONFIG_CPU_800M_DDR2_400M)
printf("\tDRAM frequency: 400MHz\n");
#elif defined(CONFIG_CPU_600M_DDR2_200M)
printf("\tDRAM frequency: 200MHz\n");
#else*/
printf("\tDRAM frequency: %dMHz\n", dram_table[dram_type_idx][dram_freq_idx]);
//#endif
/* switch (REG32(0xB800000C) & 0x0F) {
case 0x06:
case 0x0C:
dram_val = 32;
break;
case 0x04:
case 0x0A:
dram_val = 64;
break;
case 0x05:
case 0x0B:
dram_val = 128;
break;
default:
#ifdef CONFIG_DRAM_SIZE
dram_val = CONFIG_DRAM_SIZE_IN_MB;
#else
//dram_val = 32;
dram_val = REG32(0xB8000F00); // auto detect
#endif
}
REG32(0xB8000F00) = dram_val;*/
printf("\tDRAM Size: %dMB\n", dram_val);
REG32(0xb8000850) = REG32(0xb8000850) & (~(1<<7));
}
2,uboot启动的第二个阶段,编译后查看head.o->boot/arch/mips/kernel/head.S
1:
sw zero, 0(t0)
addi t0, 4
bne t0, s1, 1b
nop
nop
jal init_arch
nop
nop
init_arch ->boot\arch\mips\kernel\setup.c
asmlinkage void init_arch(int argc, char **argv, char **envp, int *prom_vec)
{
//init_icache();
//init_icache();
init_cpu_config();
// start_kernel();
jmp_func_t *jmp;
extern void start_kernel(void);
//jmp=((int)start_kernel)& ~UNCACHE_MASK;
jmp = (jmp_func_t *)(((int)start_kernel)& ~UNCACHE_MASK);
jmp();
}
直接uboot跳转kernel的代码:
void start_kernel(void) { int ret; gCHKKEY_HIT = 0; gCHKKEY_CNT = 0; IMG_HEADER_T header; SETTING_HEADER_T setting_header; #ifdef MTN_NORMAL_IPV6_Haier RTL_W32(BSP_LED_R_PIN_MUX_SEL, (RTL_R32(BSP_LED_R_PIN_MUX_SEL) & ~(BSP_LED_R_PIN_MASK) | (BSP_LED_R_PIN_MUX))); // RTL_W32(BSP_LED_R_PIN_MUX_SEL,1); /* turn on gpio pin */ RTL_W32(BSP_GPIO_CNR_REG(BSP_LED_R_PIN), (RTL_R32(BSP_GPIO_CNR_REG(BSP_LED_R_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_LED_R_PIN))))); /* set gpio as output */ RTL_W32(BSP_GPIO_DIR_REG(BSP_LED_R_PIN), (RTL_R32(BSP_GPIO_DIR_REG(BSP_LED_R_PIN)) | (1 << BSP_GPIO_BIT(BSP_LED_R_PIN)))); RTL_W32(BSP_LED_G_PIN_MUX_SEL, (RTL_R32(BSP_LED_G_PIN_MUX_SEL) & ~(BSP_LED_G_PIN_MASK) | (BSP_LED_G_PIN_MUX))); /* turn on gpio pin */ RTL_W32(BSP_GPIO_CNR_REG(BSP_LED_G_PIN), (RTL_R32(BSP_GPIO_CNR_REG(BSP_LED_G_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_LED_G_PIN))))); /* set gpio as output */ RTL_W32(BSP_GPIO_DIR_REG(BSP_LED_G_PIN), (RTL_R32(BSP_GPIO_DIR_REG(BSP_LED_G_PIN)) | (1 << BSP_GPIO_BIT(BSP_LED_G_PIN)))); RTL_W32(BSP_LED_R_PIN_MUX_SEL, (RTL_R32(BSP_LED_R_PIN_MUX_SEL) & ~(BSP_LED_R_PIN_MASK) | (BSP_LED_R_PIN_MUX))); // RTL_W32(BSP_LED_R_PIN_MUX_SEL,1); /* turn on gpio pin */ RTL_W32(BSP_GPIO_CNR_REG(BSP_LED_R_PIN), (RTL_R32(BSP_GPIO_CNR_REG(BSP_LED_R_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_LED_R_PIN))))); /* set gpio as output */ RTL_W32(BSP_GPIO_DIR_REG(BSP_LED_R_PIN), (RTL_R32(BSP_GPIO_DIR_REG(BSP_LED_R_PIN)) | (1 << BSP_GPIO_BIT(BSP_LED_R_PIN)))); RTL_W32(BSP_LED_G_PIN_MUX_SEL, (RTL_R32(BSP_LED_G_PIN_MUX_SEL) & ~(BSP_LED_G_PIN_MASK) | (BSP_LED_G_PIN_MUX))); /* turn on gpio pin */ RTL_W32(BSP_GPIO_CNR_REG(BSP_LED_G_PIN), (RTL_R32(BSP_GPIO_CNR_REG(BSP_LED_G_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_LED_G_PIN))))); /* set gpio as output */ RTL_W32(BSP_GPIO_DIR_REG(BSP_LED_G_PIN), (RTL_R32(BSP_GPIO_DIR_REG(BSP_LED_G_PIN)) | (1 << BSP_GPIO_BIT(BSP_LED_G_PIN)))); Set_LED_R_ON(); Set_LED_G_OFF(); mdelay(1000); Set_LED_R_OFF(); Set_LED_G_ON(); mdelay(1000); Set_LED_R_ON(); Set_LED_G_OFF(); mdelay(1000); Set_LED_R_OFF(); Set_LED_G_ON(); mdelay(1000); Set_LED_G_ON(); Set_LED_R_OFF(); #else /* set pin mux as gpio */ RTL_W32(BSP_POWER_LED_PIN_MUX_SEL, (RTL_R32(BSP_POWER_LED_PIN_MUX_SEL) & ~(BSP_POWER_LED_PIN_MASK) | (BSP_POWER_LED_PIN_MUX))); /* turn on gpio pin */ RTL_W32(BSP_GPIO_CNR_REG(BSP_POWER_LED_PIN), (RTL_R32(BSP_GPIO_CNR_REG(BSP_POWER_LED_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_POWER_LED_PIN))))); /* set gpio as output */ RTL_W32(BSP_GPIO_DIR_REG(BSP_POWER_LED_PIN), (RTL_R32(BSP_GPIO_DIR_REG(BSP_POWER_LED_PIN)) | (1 << BSP_GPIO_BIT(BSP_POWER_LED_PIN)))); /* set data */ /* led on */ RTL_W32(BSP_GPIO_DAT_REG(BSP_POWER_LED_PIN), (RTL_R32(BSP_GPIO_DAT_REG(BSP_POWER_LED_PIN)) | (0 << BSP_GPIO_BIT(BSP_POWER_LED_PIN)))); mdelay(1000); /* led off */ RTL_W32(BSP_GPIO_DAT_REG(BSP_POWER_LED_PIN), (RTL_R32(BSP_GPIO_DAT_REG(BSP_POWER_LED_PIN)) | (~(0 << BSP_GPIO_BIT(BSP_POWER_LED_PIN))))); mdelay(1000); /*second led on */ RTL_W32(BSP_GPIO_DAT_REG(BSP_POWER_LED_PIN), (RTL_R32(BSP_GPIO_DAT_REG(BSP_POWER_LED_PIN)) & (0 << BSP_GPIO_BIT(BSP_POWER_LED_PIN)))); #endif //------------------------------------------------------- setClkInitConsole(); initHeap(); initInterrupt(); initFlash(); #ifdef CONFIG_I2C_POLLING initI2C(); #endif #ifdef CONFIG_PCIE_INIT initPCIE(); #endif #ifdef CONFIG_CRYPTO_DEV_REALTEK rtl_crypto_init(); #endif //Init_GPIO(); //MxSpdupThanLexra(); //wei add #if defined(CONFIG_POST_ENABLE) ret = POSTRW_API(); #endif /* FullAndSemiReset(); rtl8651_restartAsicEthernetPHYNway(1,1); rtl8651_restartAsicEthernetPHYNway(2,2); rtl8651_restartAsicEthernetPHYNway(3,3); rtl8651_restartAsicEthernetPHYNway(4,4); */ showBoardInfo(); #if defined(CONFIG_POST_ENABLE) if(ret == 0) return; #endif #ifdef CONFIG_BOOT_RESET_ENABLE /* set pin mux as gpio */ RTL_W32(BSP_RESET_BTN_PIN_MUX_SEL, (RTL_R32(BSP_RESET_BTN_PIN_MUX_SEL) & ~(BSP_RESET_BTN_PIN_MASK) | (BSP_RESET_BTN_PIN_MUX))); /* turn on gpio pin */ RTL_W32(BSP_GPIO_CNR_REG(BSP_RESET_BTN_PIN), (RTL_R32(BSP_GPIO_CNR_REG(BSP_RESET_BTN_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_RESET_BTN_PIN))))); /* set gpio as input */ RTL_W32(BSP_GPIO_DIR_REG(BSP_RESET_BTN_PIN), (RTL_R32(BSP_GPIO_DIR_REG(BSP_RESET_BTN_PIN)) & (~(1 << BSP_GPIO_BIT(BSP_RESET_BTN_PIN))))); #endif #if 0 DDR_short_ZQ(); #endif #if 0 #define REG32(reg) (*(volatile unsigned int *)(reg)) REG32(0xb8010000)|=(3<<28); //set b8010000 bit 29-28=0b11 (burst size = 128 bytes)//0xf4000000 #endif #if 1 //defined(CONFIG_RTL8197F) && (defined (CONFIG_SW_8367R) || defined (CONFIG_SW_83XX)) && defined(CONFIG_LAN_WAN_ISOLATION) //init_97f_8367r(); if (swCore_init()) { dprintf("\nSwitch core initialization failed!\n"); return; } #elif defined(CONFIG_RTL8197F) && (defined (CONFIG_SW_8367R) || defined (CONFIG_SW_83XX)) //pull low for 8367R #define GPIO_RESET 26 // GPIO_H2 REG32(PIN_MUX_SEL14) = (REG32(PIN_MUX_SEL14) & ~(0xF<<28)) | (2<<28); REG32(PEFGHCNR) &= ~(1<<GPIO_RESET); REG32(PEFGHDIR) |= (1<<GPIO_RESET); // for 8367r h/w reset pin REG32(PEFGHDAT) &= ~(1<<GPIO_RESET); #endif #ifdef SUPPORT_TFTP_CLIENT extern volatile unsigned int last_sent_time; extern unsigned int tftp_from_command; extern int retry_cnt; retry_cnt = 0; tftp_from_command = 0; last_sent_time = 0; eth_startup(0); sti(); tftpd_entry(1); #endif return_addr=0; //ret=check_image (&header,&setting_header); ret = 1; //do check_image() after detect ESC!!! #if defined(CONFIG_NAND_FLASH_BOOTING) #define MAX_MOUNT_ROOTFS_TIMES 5 if(REG32(0xb8019004) > MAX_MOUNT_ROOTFS_TIMES){ REG32(0xb8019004) = 0; ret = 0; } #endif #ifdef CONFIG_SD_CARD_BOOTING ret=1; #endif doBooting(ret, return_addr, &header); }