第一阶段:探索启动代码
首先进入/cpu/arm920t/start.S
6.2.1 关闭AT9200写的LED跳转
orr r0,r0,#0xd3 msr cpsr,r0 #bl coloured_LED_init #bl red_LED_on
#ifdef CONFIG_MINI2440_LED
bl MINI2440_LED_on
#endif
6.2.2 修改CPU频率初始化设置
2410和2440想必一个不同的地方就是PLL的初始化参数不一样,。这里一开始就讲频率提升到405MHz。其中还包括中断掩码的修正。
@ u-boot-2010.03/cpu/arm920t/start.S bne copyex #endif #if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) /* turn off watchdog */ #if defined(CONFIG_S3C2400) #define INTSUBMSK 0x4A00001C #define CLKDIV 0x4C000014 #endif #define MDIV_405 (0x7f<<12) #define PSDIV_405 (2<<4)|(1<<0) #define MDIV_200 (0xA1<<12) #define PSDIV_200 (3<<4)|(1<<0) ldr r0,=pWTCON mov r1,#0x0 str r0,[r1] ldr r0, = INTMSK ldr r1,[r0]
6.2.3 修改lowlevel_init.S文件
为了匹配mini2440的存储器配置,需要修改lowlevel_init.S文件。这个所连接的NorFlash位数有关。置于SDRAM的参数,可以从芯片手册查到。SDRAM参数相关就是在这里修改的。
6.2.4 修改代码重定向部分
Tekkaman Ninja从2009.08开始就在启动时增加了启动时检测自身是否已经在SDRAM中,已经芯片是NorBoot还是NandBoot的机制,来决定代码重定向的方式,是的编译出的bin文件可以同时烧入Nand Flash和Nor Flash,以及OpenJTAG载入进行调试。
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #endif /***************Check code position*************************/ adr r0,_start ldr r1,TEXT_BASE cmp r0,r1 beq stack_setup /**************Check boot flash****************************/ ldr r0,=((4<<28)|(3<<4)|(3<<2)) /* address of Internal SRAM 0x4000003C */ mov r1,#0 str r1,[r0] mov r1,#0x3C ldr r0,[r1] cmp r0,#0 bne recolate /* recovery */ ldr r0,=(0xdeadbeef) ldr r1,=((4<<28)|(3<<4)|(3<<2)) str r0,[r1] /*************Nand Boot**********************************/ #define LENGTH_UBOOT 0x60000 #define NAND_CTL_BASE 0x4E000000 #ifdef CONFIG_S3C2440 #define oNFCONF 0x00 #define oNFCONT 0x04 #define oNFCMD 0x08 #define oNFSTAT 0x20 @reset NAND mov r1,#NAND_CTL_BASE ldr r2,=((7<<12)|(7<<8)|(7<<4)) str r2,[r1,#oNFCONF] ldr r2,[r1,#oNFCONF] ....... ldr r2,[r1,#oNFCONT] orr r2,r2,#0x2 str r2,[#oNFCONT] ldr sp,DW_STACK_START mov fp,#0 ldr r0,=TEXT_BASE mov r1,#0x0 mov r2,#LENGTH_UBOOT bl nand_read_ll tst r0,#0x0 beq ok_nand_read bad_nand_read: loop2: b loop2 ok_nand_read: mov r0,#0 ldr r1,=TEXT_BASE mov r2,#0x400 go_next: ldr r3,[r0],#4 ldr r4,[r1],#4 teq r3,r4 bne nomatch subs r2,r2,#4 beq stack_setup bne go_next nomatch: loop3: b loop3 #endif
/***************Nor Flash***************************/
relocate:
/************check for magic number *************/
ldr r1,=0xdeadbeef
cmp r0,r1
bne loop3
adr r0,_start
ldr r1,_TEXT_BASE
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
......
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
.align
DW_STACK_STACK
.word STACK_BASE + STACK_SIZE - 4
在上面添加的代码有一个跳转:bl nand_read_ll,它跳入是新增的C语言文件(/board/Samsung/mini2440/nand_read.c)中的函数,这个文件原本是vivi的代码,经过修改,并支持不同的Nand Flash芯片。
1 #include <common.h> 2 #include <linux/mtd/nand.h> 3 4 #define __REGb(x) (*(volatile unsigned char *)(x)) 5 #define __REGw(x) (*(volatile unsigned short *)(x)) 6 #define __REGi(x) (*(volatile unsigned int *)(x)) 7 #define NF_BASE 0x4e000000 8 #if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) 9 #define NFCONF __REGi(NF_BASE + 0x0) 10 #define NFCONT __REGi(NF_BASE + 0x4) 11 #define NFCMD __REGb(NF_BASE + 0x8) 12 #define NFADDR __REGb(NF_BASE + 0xc) 13 #define NFDATA __REGb(NF_BASE + 0x10) 14 #define NFDATA16 __REGw(NF_BASE + 0x10) 15 #define NFSTAT __REGb(NF_BASE + 0x20) 16 #define NFSTAT_BUSY 1 17 #define nand_select() (NFCONT &= ~(1 << 1)) 18 #define nand_deselect() (NFCONT |= (1 << 1)) 19 #define nand_clear_RnB() (NFSTAT |= (1 << 2)) 20 #endif 21 22 static inline void nand_wait(void) 23 { 24 int i; 25 26 while (!(NFSTAT & NFSTAT_BUSY)) 27 for (i=0; i<10; i++); 28 } 29 30 struct boot_nand_t { 31 int page_size; 32 int block_size; 33 int bad_block_offset; 34 }; 35 36 static int is_bad_block(struct boot_nand_t * nand, unsigned long i) 37 { 38 unsigned char data; 39 unsigned long page_num; 40 41 nand_clear_RnB(); 42 page_num = i >> 11; /* addr / 2048 */ 43 NFCMD = 0x00; /*Read Command*/ 44 NFADDR = nand->bad_block_offset & 0xff; 45 NFADDR = (nand->bad_block_offset >> 8) & 0xff; 46 NFADDR = page_num & 0xff; 47 NFADDR = (page_num >> 8) & 0xff; 48 NFADDR = (page_num >> 16) & 0xff; 49 NFCMD = 0x70; /*Read Status Command*/ 50 nand_wait(); 51 data = (NFDATA & 0xff); 52 if (data != 0xff) /*If First Byte is Not 0xFF, Current Block is Bad*/ 53 return 1; 54 55 return 0; 56 } 57 58 static int nand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, 59 unsigned long addr) 60 { 61 unsigned short *ptr16 = (unsigned short *)buf; 62 unsigned int i, page_num; 63 nand_clear_RnB(); 64 NFCMD = 0x00; 65 page_num = addr >> 11; /* addr / 2048 */ /*Page Address*/ 66 /* Write Address */ 67 NFADDR = 0; /* Read Data Page by Page*/ 68 NFADDR = 0; 69 NFADDR = page_num & 0xff; 70 NFADDR = (page_num >> 8) & 0xff; 71 NFADDR = (page_num >> 16) & 0xff; 72 NFCMD = 0x30; 73 nand_wait(); 74 for (i = 0; i < (nand->page_size>>1); i++) /*Read Data in This Page*/ 75 { 76 *ptr16 = NFDATA16; 77 ptr16++; 78 } 79 return nand->page_size; 80 } 81 82 extern unsigned int dynpart_size[]; 83 84 /* low level nand read function */ 85 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) 86 { 87 int i, j; 88 unsigned short nand_id; 89 struct boot_nand_t nand; 90 91 /* chip Enable */ 92 nand_select(); 93 nand_clear_RnB(); 94 95 for (i = 0; i < 10; i++) 96 ; 97 98 nand.page_size = 2048; 99 nand.block_size = 128 * 1024; 100 nand.bad_block_offset = nand.page_size; 101 102 //if ((start_addr & (nand.block_size-1)) || (size & ((nand.block_size-1)))) 103 //return -1; /* invalid alignment */ 104 105 for (i=start_addr; i < (start_addr + size);) { 106 if (i & (nand.block_size-1)== 0)/*i equals to the next block's initial address*/ 107 { 108 if (is_bad_block(&nand, i) || 109 is_bad_block(&nand, i + nand.page_size)) { 110 /* Bad block */ 111 i += nand.block_size; 112 size += nand.block_size; 113 continue; 114 } 115 } 116 j = nand_read_page_ll(&nand, buf, i); 117 i += j; 118 buf += j; 119 } 120 121 /* chip Disable */ 122 nand_deselect(); 123 124 return 0; 125 }
在添加这个文件之后,记得要在Makefile里加上对这个文件的编译。
#修改board/Samsung/mini2440/Makefile LIB = $(obj)lib$(board).a #COBJS := sbc2410.o flash.o COBJS := nand_read.o mini2440.o flash.o SOBJS := lowlevel_init.o SRCS := $(SOBJS:.o = .S) $(COBJS:.o = .c)
到这里,启动的第一阶段就修改结束,但是在U-Boot-1.3.3之后,这些本应放在bin文件前4K的代码会被放到后面,以至启动失败。随意必须手动修改连接时使用的.lds文件,是的这些代码被放在bin文件的最前面。
#修改U-Boot-2010.03/cpu/arm920t/u-boot.lds .text: { cpu/arm920t/start.o board/Samsung/mini2440/lowlevel_init.o board/Samsung/mini2440/nand_read.o }