第一阶段:探索启动代码
首先进入/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 }

浙公网安备 33010602011771号