uboot 由两阶段代码组成:
•第一阶段主要步骤:
1.将cpu设置为svc模式
2.关闭mmu
3.设置外设端口地址
4.关闭watchdog
5.关闭中断
6.初始化时钟
7.初始化内存DRAM
8.把 nandflash 中的代码搬移到链接地址处
9.初始化堆栈
10.清bss段
11.使用与地址相关的跳转指令,跳转到 c 入口处。
OK6410上的启动代码如下:
@start.S .text .global _start _start: /*set the cpu to svc32 mode*/ mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0xd3 msr cpsr,r0 /*disable_mmu*/ mcr p15,0,r0,c7,c7,0 mrc p15,0,r0,c1,c0,0 bic r0,r0,#0x00000007 mcr p15,0,r0,c1,c0,0 /*peri port setup*/ ldr r0,=0x70000000 orr r0,r0,#0x13 mcr p15,0,r0,c15,c2,4 /*Disable Watchdog *if you don‘t disable watchdog,because you don‘t to feed dog,so the CPU will conti *nue reboot. */ ldr r0,=0x7e000000 orr r0,r0,#0x4000 mov r1,#0 str r1,[r0] /*Disable interrupt*/ mvn r1,#0 ldr r0,=0x71200014 str r1,[r0] ldr r0,=0x71300014 str r1,[r0] /*Init clock*/ #define APLL_LOCK 0x7e00f000 #define MPLL_LOCK 0x7e00f004 #define EPLL_LOCK 0x7e00f008 #define LOCK_TIME 0xffff #define OTHERS 0x7e00f900 #define CLK_DIV0 0x7e00f020 #define CLK_SRC 0x7e00f01c @ set the lock time to max ldr r0, =LOCK_TIME ldr r1, =APLL_LOCK str r0, [r1] ldr r1, =MPLL_LOCK str r0, [r1] ldr r1, =EPLL_LOCK str r0, [r1] @ set async mode ldr r0, =OTHERS ldr r1, [r0] bic r1, #0xc0 str r1, [r0] loop1: ldr r0, =OTHERS ldr r1, [r0] and r1, #0xf00 cmp r1, #0 bne loop1 @ set the divider #define DIV_VAL ( (0)|(1<<4)|(1<<8)|(1<<9)|(3<<12) ) ldr r0, =CLK_DIV0 ldr r1, =DIV_VAL str r1, [r0] @ set APLL, MPLL, EPLL #define SDIV 1 #define PDIV 3 #define MDIV 266 #define PLL_ENABLE ( 1 << 31 ) #define APLL_VAL ( (SDIV<<0)|(PDIV<<8)|(MDIV<<16)|(PLL_ENABLE) ) #define MPLL_VAL APLL_VAL #define EPLL0_VAL ( (2<<0)|(1<<8)|(32<<16)|PLL_ENABLE) #define EPLL1_VAL ( 0 ) #define APLL_CON 0x7e00f00c #define MPLL_CON 0x7e00f010 #define EPLL_CON0 0x7e00f014 #define EPLL_CON1 0x7e00f018 ldr r0, =APLL_CON ldr r1, =APLL_VAL str r1, [r0] ldr r0, =MPLL_CON ldr r1, =MPLL_VAL str r1, [r0] ldr r0, =EPLL_CON0 ldr r1, =EPLL0_VAL str r1, [r0] ldr r0, =EPLL_CON1 ldr r1, =EPLL1_VAL str r1, [r0] @ select the source ldr r0, =CLK_SRC mov r1, #7 str r1, [r0] init_mem: ldr r0,=0x7e00f120 mov r1, #0x8 str r1, [r0] ldr r0, =0x7e001004 mov r1, #0x4 str r1, [r0] ldr r0, =0x7e001010 ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001014 mov r1, #(3 << 1) str r1, [r0] ldr r0, =0x7e001018 mov r1, #0x1 str r1, [r0] ldr r0, =0x7e00101c mov r1, #0x2 str r1, [r0] ldr r0, =0x7e001020 ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001024 ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001028 ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e00102c ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001030 ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001034 ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001038 ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e00103c mov r1, #0x07 str r1, [r0] ldr r0, =0x7e001040 mov r1, #0x02 str r1, [r0] ldr r0, =0x7e001044 ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e001048 ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, [r0] ldr r0, =0x7e00100c ldr r1, =0x00010012 str r1, [r0] ldr r0, =0x7e00104c ldr r1, =0x0b45 str r1, [r0] ldr r0, =0x7e001200 ldr r1, =0x150f8 str r1, [r0] ldr r0, =0x7e001304 mov r1, #0x0 str r1, [r0] ldr r0, =0x7e001008 ldr r1, =0x000c0000 str r1, [r0] ldr r1, =0x00000000 str r1, [r0] ldr r1, =0x00040000 str r1, [r0] ldr r1, =0x000a0000 str r1, [r0] ldr r1, =0x00080032 str r1, [r0] ldr r0, =0x7e001004 mov r1, #0x0 str r1, [r0] check_dmc1_ready: ldr r0, =0x7e001000 ldr r1, [r0] mov r2, #0x3 and r1, r1, r2 cmp r1, #0x1 bne check_dmc1_ready nop /*prepare C language environment*/ /* *copy_to_ram: * ldr r0,=0x0c000000 * ldr r1,=0x50000000 * add r3,r0,#1024*4 *copy_loop: * ldr r2,[r0],#4 * str r2,[r1],#4 * cmp r0,r3 * bne copy_loop */ init_stack: ldr sp,=0x54000000 copy_to_ram: adr r0, _start /* »ñµÃ_startÖ¸ÁǰËùÔڵĵØÖ· : 0*/ ldr r1, =_start /* _startµÄÁ´½ÓµØÖ· 0x51000000 */ ldr r2, =bss_start /* bss¶ÎµÄÆðʼÁ´½ÓµØÖ· */ sub r2, r2, r1 cmp r0,r1 beq clean_bss bl copy2ddr cmp r0, #0 bne halt clean_bss: ldr r0,=bss_start ldr r1,=bss_end cmp r0,r1 beq to_ddr clean_loop: mov r2,#0 str r2,[r0],#4 cmp r0,r1 bne clean_loop to_ddr: bl light_led ldr pc,=main light_led: ldr r1, =0x7F008820 ldr r0, =0x1111 str r0, [r1] ldr r1, =0x7F008824 mov r0,#0xe str r0,[r1] mov pc, lr halt: b halt
//nand.c #define MEM_SYS_CFG (*((volatile unsigned long *)0x7E00F120)) #define NFCONF (*((volatile unsigned long *)0x70200000)) #define NFCONT (*((volatile unsigned long *)0x70200004)) #define NFCMMD (*((volatile unsigned long *)0x70200008)) #define NFADDR (*((volatile unsigned long *)0x7020000C)) #define NFDATA (*((volatile unsigned char *)0x70200010)) #define NFSTAT (*((volatile unsigned long *)0x70200028)) #define NAND_DISABLE_CE() (NFCONT |= (1 << 1)) #define NAND_ENABLE_CE() (NFCONT &= ~(1 << 1)) #define NF_TRANSRnB() do { while(!(NFSTAT & (1 << 0))); } while(0) #define NAND_CMD_RESET 0xff #define NAND_CMD_READID 0x90 #define NAND_CMD_READ0 0 #define NAND_CMD_READSTART 0x30 void nand_select(void) { NFCONT &= ~(1<<1); } void nand_deselect(void) { NFCONT |= (1<<1); } void nand_cmd(unsigned char cmd) { NFCMMD = cmd; } void nand_addr(unsigned char addr) { NFADDR = addr; } unsigned char nand_get_data(void) { return NFDATA; } void wait_ready(void) { while ((NFSTAT & 0x1) == 0); } void nand_reset(void) { /* Ñ¡ÖÐ */ nand_select(); /* ·¢³ö0xffÃüÁî */ nand_cmd(0xff); /* µÈ´ý¾ÍÐ÷ */ wait_ready(); /* È¡ÏûÑ¡ÖÐ */ nand_deselect(); } void nand_init(void) { /* ÈÃxm0csn2ÓÃ×÷nand flash cs0 ƬѡÒý½Å */ MEM_SYS_CFG &= ~(1<<1); /* ÉèÖÃʱ¼ä²ÎÊý:hclk = 7.5ns */ #define TACLS 0 #define TWRPH0 3 #define TWRPH1 1 NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4)); NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4)); /* ʹÄÜnand flash controller */ NFCONT |= 1; nand_reset(); } void nand_send_addr(unsigned int addr) { #if 0 unsigned int page = addr / 2048; unsigned int colunm = addr & (2048 - 1); /* ÕâÁ½¸öµØÖ·±íʾ´ÓÒ³ÄÚÄÄÀ↑ʼ */ nand_addr(colunm & 0xff); nand_addr((colunm >> 8) & 0xff); /* ÏÂÃæÈý¸öµØÖ·±íʾÄÄÒ»Ò³ */ nand_addr(page & 0xff); nand_addr((page >> 8) & 0xff); nand_addr((page >> 16) & 0xff); #else nand_addr(addr & 0xff); /* a0~a7 */ nand_addr((addr >> 8) & 0x7); /* ³ÌÐòµÄ½Ç¶È: a8~a10 */ nand_addr((addr >> 11) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a11~a18 */ nand_addr((addr >> 19) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a19~a26 */ nand_addr((addr >> 27) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a27 ~ */ #endif } int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len) { unsigned int addr = nand_start; int i, count = 0; unsigned char *dest = (unsigned char *)ddr_start; /* Ñ¡ÖÐоƬ */ nand_select(); while (count < len) { /* ·¢³öÃüÁî0x00 */ nand_cmd(0x00); /* ·¢³öµØÖ· */ nand_send_addr(addr); /* ·¢³öÃüÁî0x30 */ nand_cmd(0x30); /* µÈ´ý¾ÍÐ÷ */ wait_ready(); /* ¶ÁÊý¾Ý */ for (i = 0; i < 2048 && count < len; i++) { dest[count++] = nand_get_data(); } addr += 2048; } /* È¡ÏûƬѡ */ nand_deselect(); return 0; } static int nandll_read_page (unsigned char *buf, unsigned long addr, int large_block) { int i; int page_size = 512; if (large_block==2) page_size = 4096; NAND_ENABLE_CE(); // Ñ¡ÖÐnand NFCMMD = NAND_CMD_READ0; /* Write Address */ NFADDR = 0; if (large_block) NFADDR = 0; NFADDR = (addr) & 0xff; NFADDR = (addr >> 8) & 0xff; NFADDR = (addr >> 16) & 0xff; if (large_block) NFCMMD = NAND_CMD_READSTART; NF_TRANSRnB(); for(i=0; i < page_size; i++) { *buf++ = NFDATA; } NAND_DISABLE_CE(); return 0; } int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len) { unsigned char *dest = (unsigned char *)ddr_start; int i; /* ³õʼ»¯nand flash controller */ nand_init(); /* ¶Ánand flash */ /* Read pages */ for (i = 0; i < 4; i++, dest+=2048){ nandll_read_page(dest, i, 2); } /* Read pages */ for (i = 4; i < ((len+4096)>>13); i++, dest+=8192) { nandll_read_page(dest, i, 2); } return 0; }
//main.c #define rGPMCON (*(volatile unsigned *)(0x7F008820)) #define rGPMDAT (*(volatile unsigned *)(0x7F008824)) #define rGPMPUD (*(volatile unsigned *)(0x7F008828)) void msDelay(int time) { volatile unsigned int i,j; for (i=0;i<20000;i++) for(j=0;j<time;j++); } void GPIO_Init(void) { rGPMCON = 0x11111; rGPMPUD = 0x00; rGPMDAT = 0x1F; } void LedTest(void) { volatile unsigned int i; while(1) { for(i=0;i<4;i++) { rGPMDAT =~(1<<i); msDelay(10); } } } int main() { GPIO_Init(); LedTest(); return 0; }
总结如下:
第一阶段启动代码主要完成此阶段所需硬件的初始化。初始化 c 语言运行环境,即初始化堆栈。进入 c 语言,跳到第二阶段。
时间: 2024-11-08 23:13:44