继ok6410 u-boot-2012.04.01移植一后修改代码,对ok6410单板初始化,主要包括时钟、串口、NAND、DDR等初始化。这些工作在以前的裸板程序都写了,直接拿来用。我觉得先写裸板程序对移植u-boot还是很有帮助的,以前写的裸板代码不管是在u-boot移植还是后面的驱动开发,都用得着。
开发环境:
系统:ubuntu 10.04.4
单板:ok6410
NAND FLASH:K9GAG08U0D 2048MB
NOR Flash:EN29LV160AB 2MB
DDR:K4X1G163PCX2 256MB
NET:DM9000AEP
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
目标:
1.板级初始化,支持单板ok6410
2.增加菜单update功能
3.修改u-boot,支持NAND启动
4.增加MLC NAND支持
5.支持DM9000,网卡下载程序
6.修改环境变量以及mtdpart分区
7.u-boot裁剪及制作补丁
一、修改时钟配置
查看代码,从start.S开始,发现时钟、内存、NAND等都在bllowlevel_init完成,进入board\samsung\smdk6410\lowlevel_init.S:修改95: bl system_clock_init,将时钟初始化换成如下代码(以前写的裸板代码):
board\samsung\smdk6410\lowlevel_init.S 151:system_clock_init:
system_clock_init: //ldr r0, =ELFIN_CLOCK_POWER_BASE /* 0x7e00f000 */ /* 1.设置LOCK_TIME */ ldr r0, =0x7E00F000 /* APLL_LOCK */ ldr r1, =0x0000FFFF str r1, [r0] str r1, [r0, #4] /* MPLL_LOCK */ str r1, [r0, #8] /* EPLL_LOCK */ #define OTHERS 0x7e00f900 @ set async mode /* 当CPU时钟 != HCLK时,要设为异瞈u0153模蔦u0153 */ ldr r0, =OTHERS ldr r1, [r0] bic r1, r1, #0xc0 /* 1100,0000 */ str r1, [r0] loop1: /* 等\u017d钡\u0153CPU\u0153胍觳\u0153模蔦u0153 */ ldr r0, =OTHERS ldr r1, [r0] and r1, r1, #0xf00 cmp r1, #0 bne loop1 /* SYNC667 */ /* MISC_CON[19] = 0 */ #define ARM_RATIO 0 /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1) */ #define HCLKX2_RATIO 1 /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */ #define HCLK_RATIO 1 /* HCLK = HCLKX2 / (HCLK_RATIO + 1) */ #define PCLK_RATIO 3 /* PCLK = HCLKX2 / (PCLK_RATIO + 1) */ #define MPLL_RATIO 0 /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) */ ldr r0, =0x7E00F020 /* CLK_DIV0 */ ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12) str r1, [r0] /* 2.配置时钟 */ /* 2.1 配置APLL */ /* 2.1.1 设置APLL * 2.1.2 MUXAPLL * 2.1.3 SYNC667 * 2.1.4 DIVAPLL */ #define APLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1)) ldr r0, =0x7E00F00C ldr r1, =APLL_CON_VAL str r1, [r0] /* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */ /* 2.2 配置MPLL */ /* 2.2.1 设置MPLL * 2.2.2 MUXMPLL * 2.2.3 SYNCMUX * 2.2.4 SYNC667 * 2.2.5 HCLKX2_RATIO * 2.2.6 PCLK_RATIO */ #define MPLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1)) ldr r0, =0x7E00F010 ldr r1, =MPLL_CON_VAL str r1, [r0] /* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */ /* 3.选择PLL的输出作为时钟診u017d */ ldr r0, =0x7E00F01C ldr r1, =0x03 str r1, [r0] mov pc, lr
二、修改串口初始化
board\samsung\smdk6410\lowlevel_init.S 226:uart_asm_init:换成如下代码
uart_asm_init: /* set GPIO to enable UART */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x220022 str r1, [r0, #GPACON_OFFSET] ldr r0, =0x7F005000/*ULCON0 = 0x3;*/ ldr r1, =0x3 str r1, [r0] ldr r0, =0x7F005004/*UCON0 = 0x5;*/ ldr r1, =0x5 str r1, [r0] ldr r0, =0x7F005008/*UFCON0 = 0x07; FIFO enable */ ldr r1, =0x07 str r1, [r0] ldr r0, =0x7F00500C/*UMCON0 = 0;*/ ldr r1, =0x00 str r1, [r0] ldr r0, =0x7F005028/*UBRDIV0 = 35;*/ ldr r1, =0x23 str r1, [r0] ldr r0, =0x7F00502C/*UDIVSLOT0 = 0x1;*/ ldr r1, =0x01 str r1, [r0] mov pc, lr
三、修改NAND、DDR初始化代码
把board\samsung\smdk6410\lowlevel_init.S关于NAND、DDR初始化部分代码去掉,我们换成C语言代码在start.S实现
104://bl nand_asm_init
107:/* Memory subsystem address 0x7e00f120 */
//ldrr0, =ELFIN_MEM_SYS_CFG
/* Xm0CSn2 = NFCON CS0, Xm0CSn3 = NFCON CS1 */
//movr1, #S3C64XX_MEM_SYS_CFG_NAND
//strr1, [r0]
//blmem_ctrl_asm_init
/* Wakeup support. Don't know if it's going to be used, untested. */
//ldr r0, =(ELFIN_CLOCK_POWER_BASE + RST_STAT_OFFSET)/*RST_STAT*/
/*ldr r1, [r0]
bicr1, r1, #0xfffffff7
cmpr1, #0x8
beqwakeup_reset
1:
movlr, r12
movpc, lr
wakeup_reset:
*/
/* Clear wakeup status register */
//ldr r0, =(ELFIN_CLOCK_POWER_BASE + WAKEUP_STAT_OFFSET)/*WAKEUP_STAT*/
//ldr r1, [r0]
//str r1, [r0]
/* LED test */
//ldr r0, =ELFIN_GPIO_BASE
//ldr r1, =0x9
//str r1, [r0, #GPMDAT_OFFSET]
/* Load return address and jump to kernel */
//ldr r0, =(ELFIN_CLOCK_POWER_BASE + INF_REG0_OFFSET)/*INFORM0*/
/* r1 = physical address of s3c6400_cpu_resume function */
//ldr r1, [r0]
/* Jump to kernel (sleep-s3c6400.S) */
//mov pc, r1
movlr, r12
mov pc, lr
nop
nop
接着在arch\arm\cpu\arm1176\start.S中增加对NAND、DDR等支持
在225:bllowlevel_init后增加如下代码
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)/*sp=0x0c00if80 ISRAM*/
bicsp, sp, #7 /* 8-byte alignment for ABI compliance */
bl ddr_init_ll
bl nand_init_ll
bldm9000aep_init
mov r0, #0
ldr r1, _TEXT_BASE
ldr r2, _bss_start_ofs
bl copy_code_to_sdram
bl clear_bss
ldr pc, =call_board_init_f/*from ISRAM jump to SDRAM*/
上面函数的实现,直接拷贝以前的update裸板代码。直接在board\samsung\smdk6410增加sdram.c、init.c两个文件。代码如下
文件sdram.c:
//#include <common.h> #define MEMCCMD0x7e001004 #define P1REFRESH0x7e001010 #define P1CASLAT0x7e001014 #define MEM_SYS_CFG0x7e00f120 #define P1MEMCFG0x7e00100c #define P1T_DQSS0x7e001018 #define P1T_MRD0x7e00101c #define P1T_RAS0x7e001020 #define P1T_RC0x7e001024 #define P1T_RCD0x7e001028 #define P1T_RFC0x7e00102c #define P1T_RP0x7e001030 #define P1T_RRD0x7e001034 #define P1T_WR0x7e001038 #define P1T_WTR0x7e00103c #define P1T_XP0x7e001040 #define P1T_XSR0x7e001044 #define P1T_ESR0x7e001048 #define P1MEMCFG20X7e00104c #define P1_chip_0_cfg0x7e001200 #define P1MEMSTAT0x7e001000 #define P1MEMCCMD0x7e001004 #define P1DIRECTCMD0x7e001008 #define HCLK133000000 #define nstoclk(ns)(ns/( 1000000000/HCLK)+1) #define vi *( volatile unsigned int * ) #define set_zero( addr, bit ) ( (vi addr) &= ( ~ ( 1 << (bit) ) ) ) #define set_one( addr, bit ) ( (vi addr) |= ( 1 << ( bit ) ) ) #define set_bit( addr, bit, val ) ( (vi addr) = (( vi addr)&=(~(1<<(bit))) ) | ( (val)<<(bit) ) ) #define set_2bit( addr, bit, val ) ( (vi addr) = (( vi addr)&(~(3<<(bit))) ) | ( (val)<<(bit) ) ) #define set_nbit( addr, bit, len, val ) \ ( (vi addr) = ((( vi addr)&(~(( ((1<<(len))-1) )<<(bit)))) | ( (val)<<(bit) ) )) #define get_bit( addr, bit ) ( (( vi addr ) & ( 1 << (bit) )) > 0 ) #define get_val( addr, val ) ( (val) = vi addr ) #define read_val( addr ) ( vi ( addr ) ) #define set_val( addr, val ) ( (vi addr) = (val) ) #define or_val( addr, val ) ( (vi addr) |= (val) ) void ddr_init_ll( void ) { // tell dramc to configure set_val( MEMCCMD, 0x4 ); // set refresh period set_val( P1REFRESH, nstoclk(7800) ); // set timing para set_val( P1CASLAT, ( 3 << 1 ) ); set_val( P1T_DQSS, 0x1 );// 0.75 - 1.25 set_val( P1T_MRD, 0x2 ); set_val( P1T_RAS, nstoclk(45) ); set_val( P1T_RC, nstoclk(68) ); unsigned int trcd = nstoclk( 23 ); set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) ); unsigned int trfc = nstoclk( 80 ); set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) ); unsigned int trp = nstoclk( 23 ); set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) ); set_val( P1T_RRD, nstoclk(15) ); set_val( P1T_WR, nstoclk(15) ); set_val( P1T_WTR, 0x7 ); set_val( P1T_XP, 0x2 ); set_val( P1T_XSR, nstoclk(120) ); set_val( P1T_ESR, nstoclk(120) ); // set mem cfg set_nbit( P1MEMCFG, 0, 3, 0x2 ); /* 10 column address */ /* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */ set_nbit( P1MEMCFG, 3, 3, 0x2 ); /* 13 row address */ set_zero( P1MEMCFG, 6 ); /* A10/AP */ set_nbit( P1MEMCFG, 15, 3, 0x2 ); /* Burst 4 */ set_nbit( P1MEMCFG2, 0, 4, 0x5 ); set_2bit( P1MEMCFG2, 6, 0x1 );/* 32 bit */ set_nbit( P1MEMCFG2, 8, 3, 0x3 );/* Mobile DDR SDRAM */ set_2bit( P1MEMCFG2, 11, 0x1 ); set_one( P1_chip_0_cfg, 16 );/* Bank-Row-Column organization */ // memory init set_val( P1DIRECTCMD, 0xc0000 ); // NOP set_val( P1DIRECTCMD, 0x000 );// precharge set_val( P1DIRECTCMD, 0x40000 );// auto refresh set_val( P1DIRECTCMD, 0x40000 );// auto refresh set_val( P1DIRECTCMD, 0xa0000 ); // EMRS set_val( P1DIRECTCMD, 0x80032 ); // MRS set_val( MEM_SYS_CFG, 0x0 ); // set dramc to "go" status set_val( P1MEMCCMD, 0x000 ); // wait ready while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1)); }
文件init.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)) void nand_read_ll(unsigned int nand_start, unsigned int ddr_start, unsigned int len); int isBootFromNorFlash(void) { volatile int *p = (volatile int *)0; int val; val = *p; *p = 0x12345678; if (*p == 0x12345678) { /*鍐欐垚鍔燂紝鏄痭and鍚姩*/ *p = val; return 0; } else { /*Nor涓嶈兘鍍忓唴瀛樹竴鏍峰啓*/ return 1; } } void copy_code_to_sdram(unsigned int src, unsigned int dest, unsigned int len) { int i = 0; /*濡傛灉鏄疦or鍚姩*/ unsigned char *src_start = (unsigned char *)src; unsigned char *dest_start = (unsigned char *)dest; if(isBootFromNorFlash()) { while (i < len) { dest_start[i] = src_start[i]; i++; } } else { //nand_init(); //nand_resd(src, dest, len) nand_read_ll(src, dest, len); } } static void nand_select(void) { NFCONT &= ~(1<<1); } static void nand_deselect(void) { NFCONT |= (1<<1); } static void nand_cmd(unsigned char cmd) { NFCMMD = cmd; } static void nand_addr(unsigned char addr) { NFADDR = addr; } static unsigned char nand_get_data(void) { return NFDATA; } static void nand_send_data(unsigned char data) { NFDATA = data; } static void wait_ready(void) { while ((NFSTAT & 0x1) == 0); } static void nand_reset(void) { /* 閫変腑 */ nand_select(); /* 鍙戝嚭0xff鍛戒护 */ nand_cmd(0xff); /* 绛夊緟灏辩华 */ wait_ready(); /* 鍙栨秷閫変腑 */ nand_deselect(); } void clear_bss(void) { extern int __bss_start, __bss_end__; int *p = &__bss_start; for (; p < &__bss_end__; p++) *p = 0; } void nand_init_ll(void) { /* 璁﹛m0csn2鐢ㄤ綔nand flash cs0 鐗囬€夊紩鑴?*/ MEM_SYS_CFG &= ~(1<<1); /* 璁剧疆鏃堕棿鍙傛暟 */ #define TACLS 0 #define TWRPH0 2 #define TWRPH1 1 NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4)); NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4)); /* 浣胯兘nand flash controller */ NFCONT |= 1; NFCONT &= ~(1<<16); /* 妫soft lock */ nand_reset(); } static void nand_send_addr(unsigned int addr) { #if 1 unsigned int page = addr / 4096; unsigned int colunm = addr & (4096 - 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) & 0x1f); /* 绋嬪簭鐨勮搴? a8~a12 */ nand_addr((addr >> 13) & 0xff); /* 绋嬪簭鐨勮搴? a13~a20 */ nand_addr((addr >> 21) & 0xff); /* 绋嬪簭鐨勮搴? a21~a28 */ nand_addr((addr >> 29) & 0x7); /* 绋嬪簭鐨勮搴? a29 ~ */ #endif } void nand_read_ll(unsigned int nand_start, unsigned int ddr_start, unsigned int len) { unsigned int addr = nand_start; int i = nand_start % 4096; int left = i; int count = 0; unsigned char *dest = (unsigned char *)ddr_start; unsigned char data = 0; /* 閫変腑鑺墖 */ nand_select(); while (count < len) { /* 鍙戝嚭鍛戒护0x00 */ nand_cmd(0x00); /* 鍙戝嚭鍦板潃 */ nand_send_addr(addr); /* 鍙戝嚭鍛戒护0x30 */ nand_cmd(0x30); /* 绛夊緟灏辩华 */ wait_ready(); /* 璇绘暟鎹?*/ for (; i < (4096-left) && count < len; i++)//浠庢煇椤电殑i澶勫紑濮嬭 { data = nand_get_data(); if(addr<16384)//鍓?椤垫瘡娆″彧鑳藉啓2K { if(i<(2048-left)) { dest[count++] = data; } } else { dest[count++] = data; } //dest[count++] = nand_get_data(); addr++; } i = 0; left = i; } /* 鍙栨秷鐗囬€?*/ nand_deselect(); // return 0; } void nand_erase_block_ll(unsigned long addr) { int page = addr / 4096; nand_select(); nand_cmd(0x60); nand_addr(page & 0xff); nand_addr((page >> 8) & 0xff); nand_addr((page >> 16) & 0xff); nand_cmd(0xd0); wait_ready(); nand_deselect(); } void nand_write_ll(unsigned int nand_start, unsigned char * buf, unsigned int len) { unsigned long count = 0; unsigned long addr = nand_start; int i = nand_start % 4096; int left = i; nand_select(); while (count < len) { nand_cmd(0x80); nand_send_addr(addr); for (; i < (4096-left) && count < len; i++) { if(addr<16384)//鍐欏墠2K { if(i<(2048-left))//鍓?椤垫瘡椤靛彧鑳藉啓2K { nand_send_data(buf[count++]); } } else { nand_send_data(buf[count++]); } //nand_send_data(buf[count++]); addr++; } nand_cmd(0x10); wait_ready(); i = 0; left = i; } nand_deselect(); } #define ULCON0 (*((volatile unsigned long *)0x7F005000)) #define UCON0 (*((volatile unsigned long *)0x7F005004)) #define UFCON0 (*((volatile unsigned long *)0x7F005008)) #define UMCON0 (*((volatile unsigned long *)0x7F00500C)) #define UTRSTAT0 (*((volatile unsigned long *)0x7F005010)) #define UFSTAT0 (*((volatile unsigned long *)0x7F005018)) #define UTXH0 (*((volatile unsigned char *)0x7F005020)) #define URXH0 (*((volatile unsigned char *)0x7F005024)) #define UBRDIV0 (*((volatile unsigned short *)0x7F005028)) #define UDIVSLOT0 (*((volatile unsigned short *)0x7F00502C)) #define GPACON (*((volatile unsigned long *)0x7F008000)) #define ENABLE_FIFO int getc_nowait(unsigned char *pChar) { #ifdef ENABLE_FIFO if ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0) #else if ((UTRSTAT0 & (1<<0)) == 0) #endif { return -1; } else { *pChar = URXH0; return 0; } } #define SROM_BW (*((volatile unsigned long *)0x70000000)) void dm9000aep_init(void) { SROM_BW |= (0XFF<<4); }
增加文件还要修改board\samsung\smdk6410下的Makefile:修改37行
COBJS-y:= smdk6410.o sdram.o init.o
上面的代码都是我直接从以前的裸板update程序拷贝过来的,实现了NAND、DDR初始化以及拷贝代码到内存。分析u-boot-2012.04.01的重定位写的很复杂,这里还是沿用以前那种简单的重定位,有兴趣的可以分析它的重定位代码,下面继续修改
241:修改call_board_init_f成如下:
call_board_init_f:
ldrr0,=0x00000000
blboard_init_f
/*r0=(unsigned int)id */
ldr r1, _TEXT_BASE/*link address*/
ldr sp, base_sp //add*** you must add sp, otherwise,Saving Environment to NAND...
/*jump to second step code*/
bl board_init_r
这里新用到变量base_sp ,需要定义134:增加
.globl base_sp//add***
base_sp:
.long 0
同时去掉u-boot自带的重定位代码,下面这部分代码可以全部去掉,这里没有用
/*------------------------------------------------------------------------------*/ /* * void relocate_code (addr_sp, gd, addr_moni) * * This "function" does not return, instead it continues in RAM * after relocating the monitor code. * */ .globl relocate_code relocate_code: mov r4, r0 /* save addr_sp */ mov r5, r1 /* save addr of gd */ mov r6, r2 /* save addr of destination */ /* Set up the stack */ stack_setup: mov sp, r4 adr r0, _start cmp r0, r6 beq clear_bss /* skip relocation */ mov r1, r6 /* r1 <- scratch for copy_loop */ ldr r3, _bss_start_ofs add r2, r0, r3 /* r2 <- source end address */ copy_loop: ldmia r0!, {r9-r10} /* copy from source address [r0] */ stmia r1!, {r9-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end address [r2] */ blo copy_loop #ifndef CONFIG_SPL_BUILD /* * fix .rel.dyn relocations */ ldr r0, _TEXT_BASE /* r0 <- Text base */ sub r9, r6, r0 /* r9 <- relocation offset */ ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ add r10, r10, r0 /* r10 <- sym table in FLASH */ ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ add r0, r0, r9 /* r0 <- location to fix up in RAM */ ldr r1, [r2, #4] and r7, r1, #0xff cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ b fixnext fixabs: /* absolute fix: set location to (offset) symbol value */ mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ add r1, r10, r1 /* r1 <- address of symbol in table */ ldr r1, [r1, #4] /* r1 <- symbol value */ add r1, r1, r9 /* r1 <- relocated sym addr */ b fixnext fixrel: /* relative fix: increase location by offset */ ldr r1, [r0] add r1, r1, r9 fixnext: str r1, [r0] add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ cmp r2, r3 blo fixloop #endif #ifdef CONFIG_ENABLE_MMU enable_mmu: /* enable domain access */ ldr r5, =0x0000ffff mcr p15, 0, r5, c3, c0, 0 /* load domain access register */ /* Set the TTB register */ ldr r0, _mmu_table_base ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE ldr r2, =0xfff00000 bic r0, r0, r2 orr r1, r0, r1 mcr p15, 0, r1, c2, c0, 0 /* Enable the MMU */ mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #1 /* Set CR_M to enable MMU */ /* Prepare to enable the MMU */ adr r1, skip_hw_init and r1, r1, #0x3fc ldr r2, _TEXT_BASE ldr r3, =0xfff00000 and r2, r2, r3 orr r2, r2, r1 b mmu_enable .align 5 /* Run in a single cache-line */ mmu_enable: mcr p15, 0, r0, c1, c0, 0 nop nop mov pc, r2 skip_hw_init: #endif clear_bss: #ifndef CONFIG_SPL_BUILD ldr r0, _bss_start_ofs ldr r1, _bss_end_ofs mov r4, r6 /* reloc addr */ add r0, r0, r4 add r1, r1, r4 mov r2, #0x00000000 /* clear */ clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 bne clbss_l #ifndef CONFIG_NAND_SPL bl coloured_LED_init bl red_led_on #endif #endif
进入blboard_init_f 还要修改arch\arm\lib\board.c
在265:声明前面start.S定义的变量
extern ulong base_sp;//**add
在373行修改如下:
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = _TEXT_BASE;//0x57e0000
在439行修改如下去掉重定位,返回堆栈
base_sp = addr_sp;//**add
//relocate_code(addr_sp, id, addr);
return (unsigned int)id;
既然return (unsigned int)id;那么还要修改函数类型
259:void board_init_f(ulong bootflag)改为unsigned int board_init_f(ulong bootflag)
继续修改arch\arm\config.mk 75:
#LDFLAGS_u-boot += -pie
u-boot运行后,不管是NNAD还是NOR Flash启动,都会进行重定位,即把代码拷到内存运行,就像PC机一样程序都是在内存运行的。那么支持NAND启动的u-boot,重定位之前代码必须小于4KB,才能跑起来。分析现在较新的u-boot源码(以后在另外文章分析),代码连接时加-pie选项,重定位成位置无关代码,搞的很高级,不利于像S3C2440这样片内SRAM十分有限的SOC跑。这里修改重定位代码,支持NAND启动。故去掉-pie
在board\samsung\smdk6410/u-boot-nand.lds:38增加
board/samsung/smdk6410/libsmdk6410.o (.text)
这样做是为了保证重定位前的代码放在最前面4K以内。
上面修改了很多地方,先编译,有问题再修改
change@change:/si/OK6410/u-boot-2012.04.01$ make
board.c:259: error: conflicting types for 'board_init_f'
/si/OK6410/u-boot-2012.04.01/include/common.h:276: error: previous declaration of 'board_init_f' was here
make[1]: *** [board.o] Error 1
make[1]: Leaving directory `/si/OK6410/u-boot-2012.04.01/arch/arm/lib'
make: *** [arch/arm/lib/libarm.o] Error 2
change@change:/si/OK6410/u-boot-2012.04.01$
出错了,跟着提示include/common.h:276: error: previous declaration of 'board_init_f' was here去include/common.h:276看看
果然有问题,去掉noreturn,修改函数类型如下:
unsigned int board_init_f (ulong);
voidboard_init_r (gd_t *, ulong);
再编译change@change:/si/OK6410/u-boot-2012.04.01$ make
编译通过了,现在的程序串口应该能正常输出了
四、烧写测试
现在的u-boot肯定还是不能用,如果你想烧进去看看现象,这里介绍一种好方法烧写程序。先用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把上面编译生成的u-boot.bin拷到sd卡,接着把单板拨到sd卡启动。我的OK6410在NAND启动的情况下直接把6、7拨到on就变成SD启动了。单板SD卡启动上电,串口(115200 8 n 1)输出如下:
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 1904 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
error found: 0010
很不幸遇到error,再网上看了很多贴找到了解决方法。
在这里http://www.pc6.com/softview/SoftView_66768.html下载Aomei Partition Assistant Professional Edition 4.0,用该分区根据将以前分区删除,然后新建分区就行了,记住只选择你的SD卡盘,不要把自己系统盘给删了,那就亏大了。还是简单说明哈操作,解压进入运行PartAssist.exe,在看到最下面的sd卡盘,选择你的sd卡盘,单击左侧Delete All Partitions,再单击上面的Aplly.完成后同样的操作新建分区即可。不清楚可以问我,要是系统盘给自己格了,别怪我。重新分区后的SD卡启动如下
K
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for TE6410 Board **
** Version 1.0 (10-01-15) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 0 kB
NAND: tmp = 29
select s3c_nand_oob_mlc_128
2048 MB
SD/MMC: 1904 MB
*** Warning - bad CRC or moviNAND, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
NAND erase: device 0 whole chip
Skipping bad block at 0x00800000
Skipping bad block at 0x0e400000
Skipping bad block at 0x0e780000
Skipping bad block at 0x13b80000
Skipping bad block at 0x27a80000
Skipping bad block at 0x7e280000
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
242792 bytes read
NAND write: device 0 offset 0x0, size 0x100000
1032192 bytes written: OK
reading zImage
** Unable to read "zImage" from mmc 0:1 **
就说明u-boot.bin烧写完毕了,没有放zImage当然Unable to read "zImage"。没关系,断电将ok6410拨码开关6、7拨到off就变成NAND启动了。启动输出如下:
U-Boot 2012.04.01 (Jun 24 2013 - 23:27:16) for SMDK6400
CPU: S3C6400@532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6400
DRAM: 128 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###
还有很多问题,串口基本正常输出了。根据u-boot输出的Flash: *** failed ***,根据以往经验应该是没有检测到板子的NOR FLASH就卡住了,问题不大,好吧继续修改
进入arch/arm/lib/board.c 530修改如下
//puts(failed);
//hang();
puts("0 KB\n\r");
没有检测到就hang();,屏蔽让它输出OKB,修改后继续编译,编译OK按照上面的方法烧到单板,NAND启动输出如下:
U-Boot 2012.04.01 (Jun 24 2013 - 23:35:21) for SMDK6400
CPU: S3C6400@532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6400
DRAM: 128 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND: No oob scheme defined for oobsize 218
2048 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
Hit any key to stop autoboot: 0
SMDK6400 #
基本OK了,这篇修改的代码有点多,先写到这吧。