學習了幾個月的關於嵌入式相關的知識,之前一直覺得自己能力不夠,去研究uboot很有難度,現在通過幾個月的學習,再去研究uboot應該可以理解了,於是就開始自己的移植之旅!
首先在網上搜索關於6410uboot的移植的相關信息,資料有點少,都是關於2410的,偶然看到一篇關於《基於OK6410的u-boot2010.03移植過程》的文章,原來已經有朋友移植成功了的,我們就得參照一下,站在巨人的肩膀上嘛。我就詳細的把我移植的過程及其中遇到的問題說說:
准備階段:
主機環境:Ubuntu11.10
目標機: 飛凌-OK6410-A
編譯環境:arm-linux-gcc-4.3.2
源碼下載:ftp://ftp.denx.de/pub/u-boot/
下載u-boot-2010.03(本來想追求最新的,但這以后的版本跟這以前的就不同了,所以先把老版本弄清楚吧),我下載到桌面;
#tar xvf u-boot-2010.03.tar.bz2
#ls
你看到大多目錄跟Linux源碼結構很像,分析步驟跟分析linux源碼差不多,我們先編譯體驗一下,同時驗證一下能否編譯通過;
#cd u-boot-2010.03
#make smdk6400_config
#make
#ls
在文件夾根目錄下生成u-boot.bin文件,這就是我們要下載到開發板上的可執行文件。
源碼修改階段:
進入u-boot-2010.03/board/samsung,建立smdk6410文件夾,把smdk6400內的所有文件復制到smdk6410中,進smdk6410中將smdk6400.c改為smdk6410.c。(6400與6410大體是一樣的);
#cd board/samsung
#mkdir smdk6410
#cp smdk6400/* smdk6410/
#mv smdk6410/smdk6400.c smdk6410/smdk6410.c
進入u-boot-2010.03/include/asm-arm/arch-s3c64xx,復制s3c6400.h並改為s3c6410.h
#cd ../../include/asm-arm/arch-s3c64xx
#cp s3c6400.h s3c6410.h
進入根目錄,打開Makefile,找到下面的代碼:
smdk6400_noUSB_config \ smdk6400_config : unconfig @mkdir-p$(obj)include$(obj)board/samsung/smdk6400 @mkdir-p$(obj)nand_spl/board/samsung/smdk6400 @echo"#defineCONFIG_NAND_U_BOOT">$(obj)include/config.h @if[-z"$(findstringsmdk6400_noUSB_config,$@)"];then \ echo"RAM_TEXT=0x57e00000">>$(obj)board/samsung/smdk6400/config.tmp;\ $(MKCONFIG)$(@:_config=)armarm1176smdk6400samsungs3c64xx; \ else \ echo"RAM_TEXT=0xc7e00000">>$(obj)board/samsung/smdk6400/config.tmp;\ $(MKCONFIG)$(@:_noUSB_config=)armarm1176smdk6400samsungs3c64xx;\ fi @echo"CONFIG_NAND_U_BOOT=y">>$(obj)include/config.mk
上面是6400的配置文件,將里面的6400都改為6410;
smdk6410_noUSB_config \ smdk6410_config : unconfig @mkdir-p$(obj)include$(obj)board/samsung/smdk6410 @mkdir-p$(obj)nand_spl/board/samsung/smdk6410 @echo"#defineCONFIG_NAND_U_BOOT">$(obj)include/config.h @if[-z"$(findstringsmdk6410_noUSB_config,$@)"];then \ echo"RAM_TEXT=0x57e00000">>$(obj)board/samsung/smdk6410/config.tmp;\ $(MKCONFIG)$(@:_config=)armarm1176smdk6410samsungs3c64xx; \ else \ echo"RAM_TEXT=0xc7e00000">>$(obj)board/samsung/smdk6410/config.tmp;\ $(MKCONFIG)$(@:_noUSB_config=)armarm1176smdk6410samsungs3c64xx;\
進入u-boot-2010.03/board/samsung/smdk6410,編輯smdk6410,把#include <asm/arch/s3c6400.h> 改為 #include <asm/arch/s3c6410.h
下面就要修改啟動代碼cpu/arm1176/start.S
第一處修改:
#ifndef CONFIG_NAND_SPL /* * flush v4 I/D caches */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ /* * disable MMU stuff and caches////////////////////////////////////////////////////////////////////////////////////////// */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 2 (A) Align orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0//從后面拷貝過來的 ///////////////////////////////以下的注釋掉 /* Prepare to disable the MMU */ //adr r1, mmu_disable_phys /* We presume we're within the first 1024 bytes */ //and r1, r1, #0x3fc //ldr r2, _TEXT_PHY_BASE //ldr r3, =0xfff00000 //and r2, r2, r3 //orr r2, r2, r1 //b mmu_disable //.align 5 /* Run in a single cache-line */ //mmu_disable: // mcr p15, 0, r0, c1, c0, 0 // nop // nop // mov pc, r2 /////////////////////////////////////////////////////////////////////////////////////////////////////
第二處修改:
bl lowlevel_init /* go setup pll,mux,memory */ 之后 /* when we already run in ram, we don't need to relocate U-Boot.//////////////////////////////////////////////////////////////////// * and actually, memory controller must be configured before U-Boot * is running in ram. */ ldr r0, =0xff000fff bic r1, pc, r0 /* r0 <- current base addr of code */ ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */ bic r2, r2, r0 /* r0 <- current base addr of code */ cmp r1, r2 /* compare r0, r1 */ beq after_copy /* r0 == r1 then skip flash copy */ #ifdef CONFIG_BOOT_NAND mov r0, #0x1000 bl copy_from_nand #endif after_copy:///////////////////////////////////////////////////////////////////////////////////////////////// #ifdef CONFIG_ENABLE_MMU
上面的修改是判斷到底是從Nand Flash啟動還是RAM啟動;
1.如果是從nandflash中啟動,那么PC的值一定在4K之內。那么執行完bicr1,pc,r0 之后,r1為0。_TEXT_BASE要么等於0x57e00000,要么等於0xC7e00000.那么執行完bicr2,r2,r0 之后,r2為0x00e00000,那么不相等,則不跳轉,下面應該就是copy_from_nand。
2.如果是從ram中啟動,那么PC的值為0xx7e00000。那么執行完bicr1,pc,r0 之后,r1為0x00e00000。_TEXT_BASE要么等於0x57e00000,要么等於0xC7e00000.那么執行完bicr2,r2,r0 之后,r2為0x00e00000,那么相等,跳轉到after_copy,也就是不需要copy。承接上面分析,如果沒有完成copy,則接下來就是copy_from_nand。
第三處修改:
#ifndef CONFIG_NAND_SPL /* * we assume that cache operation is done before. (eg. cleanup_before_linux()) * actually, we don't need to do anything about cache if not use d-cache in * U-Boot. So, in this function we clean only MMU. by scsuh * * void theLastJump(void *kernel, int arch_num, uint boot_params); */ #ifdef CONFIG_ENABLE_MMU .globl theLastJump theLastJump: 之前加上以下語句 /* * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND) * r0: size to be compared * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size */////////////////////////////////////////////////////////////////////////////////////////////////////////////////// .globl copy_from_nand copy_from_nand: mov r10, lr /* save return address */ mov r9, r0 /* get ready to call C functions */ ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */ sub sp, sp, #12 mov fp, #0 /* no previous frame, so fp=0 */ mov r9, #0x1000 bl copy_uboot_to_ram //此函數需要添加,稍后說明。 3: tst r0, #0x0 bne copy_failed ldr r0, =0x0c000000 ldr r1, _TEXT_PHY_BASE 1: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne compare_failed /* not matched */ subs r9, r9, #4 bne 1b 4: mov lr, r10 /* all is OK */ mov pc, lr copy_failed: nop /* copy from nand failed */ b copy_failed compare_failed: nop /* compare failed */ b compare_failed
接着進入u-boot-2010.03/include/configs編輯smdk6410.h,添加下面的宏定義;
1.
#definevirt_to_phys(x) virt_to_phy_smdk6410(x)
2.
#defineCONFIG_SYS_PROMPT "SMDK6410#" /*MonitorCommandPrompt */
這里的”SMDK6410”可以自己修改,這就是你進入uboot的命令模式的#前面的文字。
3.
//#definePHYS_SDRAM_1_SIZE 0x08000000 /*128MBinBank#1 */ #definePHYS_SDRAM_1_SIZE 0x10000000 /*256MBinBank#1 */
修改SDRAM內存為256M的。
4.
/*NANDconfiguration*/ #defineNAND_DISABLE_CE()(NFCONT_REG|= (1<<1)) #defineNAND_ENABLE_CE()(NFCONT_REG&=~(1<<1)) #defineNF_TRANSRnB() do{while(!(NFSTAT_REG&(1<<0)));}while(0)
這里的定義是后面寫nand_cp.c要用到的宏定義
5.
/* *Architecturemagicandmachinetype */ //#define MACH_TYPE 1270/*smdk6400ID*/ #defineMACH_TYPE 1626/*smdk6410ID*/
6410的ID號;
6.
/* *Sizeofmalloc()pool */ //#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE+1024*1024) #defineCONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE+512*1024) #defineCONFIG_SYS_GBL_DATA_SIZE 128 /*sizeinbytesforinitialdata*/
修改內存大小;
7.
#defineCONFIG_BOOTDELAY 3
修改bootdelay延遲時間
8.
//#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE +0x7e00000) /*126MBinDRAM*/ #defineCONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE +0x9e00000) /*256MBinDRAM*/
修改SDROM大小;
9.
/*the PWMTImer4usesacounterof15625for10ms,soweneed*/ /*ittowrap100times (total1562500)toget1sec.*/ //#define CONFIG_SYS_HZ 1000 //atPCLK50MHz #defineCONFIG_SYS_HZ 1562500
時鍾修改;
10.
//#define CONFIG_STACKSIZE 0x40000 /*regularstack256KB*/ #defineCONFIG_STACKSIZE 0x80000 /*regularstack512KB*/
堆棧大小修改;
11.
//#define PHYS_SDRAM_1_SIZE 0x08000000 /*128MBinBank#1 */ #definePHYS_SDRAM_1_SIZE0x10000000 /*256MBinBank#1 */
Nand Flash每塊大小修改;
12.
//#define CONFIG_ENV_SIZE 0x4000 /*TotalSizeofEnvironmentSector*/ #defineCONFIG_ENV_SIZE 0x80000 /*TotalSizeofEnvironmentSector*/
Total Size of Environment Sector修改;
13.
//#define CONFIG_BOOTCOMMAND "nand read 0x50018000 0x60000 0x1c0000;"\ //"bootm0x50018000" #define CONFIG_BOOTCOMMAND "nand read 0x50018000 0x100000 0x500000;"\ "bootm0x50018000"
CONFIG_BOOTCOMMAND修改
14.
#defineCONFIG_ENV_OFFSET 0x0080000
CONFIG_ENV_OFFSET修改
15.
//#define CONFIG_SYS_NAND_PAGE_SIZE 2048 #defineCONFIG_SYS_NAND_PAGE_SIZE 4096
Nand Flash每一頁大小的修改
16.
/*NANDchipblocksize */ //#define CONFIG_SYS_NAND_BLOCK_SIZE (128*1024) #defineCONFIG_SYS_NAND_BLOCK_SIZE (512*1024)
Nand Flash每一塊大小的修改
17.
/*NANDchippageperblockcount */ //#define CONFIG_SYS_NAND_PAGE_COUNT 64 #defineCONFIG_SYS_NAND_PAGE_COUNT 128
校驗位修改
並將里面的所有6400替換為6410
接下來在u-boot-2010.03/cpu/arm1176/下面新建一個nand_cp.c文件,代碼如下:
#include<common.h> #ifdefCONFIG_S3C64XX #include<asm/io.h> #include<linux/mtd/nand.h>
#include<asm/arch/s3c6410.h> staticintnandll_read_page(uchar*buf,ulongaddr,intlarge_block) { inti; intpage_size=512; /* 2K */ if(large_block==1) page_size=2048; /* 4K */ if(large_block==2) page_size=4096; NAND_ENABLE_CE(); NFCMD_REG=NAND_CMD_READ0; /*WriteAddress*/ NFADDR_REG=0; if(large_block) NFADDR_REG=0;
NFADDR_REG=(addr)&0xff; NFADDR_REG=(addr>>8)&0xff; NFADDR_REG=(addr>>16)&0xff; /* #defineNFCMD_REG __REG(ELFIN_NAND_BASE+NFCMMD_OFFSET) #defineELFIN_NAND_BASE 0x70200000 #defineNFCMMD_OFFSET 0x08 NFCMD_REG=(*( (volatileu32*) (0x70200008) )) NFCMMD 0x70200008 NANDFlash命令設置寄存器0
#define NAND_CMD_READSTART 0x30 */ if(large_block) NFCMD_REG=NAND_CMD_READSTART; /* define NF_TRANSRnB() do{ while( !( NFSTAT_REG&(1<<0) ) ); }while(0) #define NFSTAT_REG __REG(ELFIN_NAND_BASE+NFSTAT_OFFSET) NFSTAT_REG=(*( (volatileu32*) (0x70200028) )) NFSTAT 0x70200028 NANDFlash操作狀態寄存器 */ NF_TRANSRnB();
/*forcompatibility(2460).u32cannotbeused.byscsuh*/ for(i=0;i<page_size;i++) { *buf++=NFDATA8_REG; } /* #defineNAND_DISABLE_CE()(NFCONT_REG|= (1<<1)) #defineNFCONT_REG __REG(ELFIN_NAND_BASE+NFCONT_OFFSET) #define__REG(x) (*((volatileu32*)(x))) #defineELFIN_NAND_BASE 0x70200000 #defineNFCONT_OFFSET 0x04 */ NAND_DISABLE_CE(); return0; }
staticintnandll_read_blocks(ulongdst_addr,ulongsize,int large_block) { uchar*buf=(uchar*)dst_addr; inti; uintpage_shift=9; if(large_block==1) page_shift=11; /*Readpages*/ if(large_block==2) page_shift=12; if(large_block==2) { /*Readpages*/ for(i=0;i<4;i++,buf+=(1<<(page_shift-1))) { nandll_read_page(buf,i,large_block); } /*Readpages*/ /* 0x3c000 = 111100000000000000 */
for(i=4;i<(0x3c000>>page_shift);i++,buf+=(1<<page_shift)) { nandll_read_page(buf,i,large_block); } } else { for(i=0;i<(0x3c000>>page_shift);i++,buf+=(1<<page_shift)) { nandll_read_page(buf,i,large_block); } } return0;
} intcopy_uboot_to_ram(void) { intlarge_block =0; inti; vu_charid; /* #defineNAND_ENABLE_CE() (NFCONT_REG&=~(1<<1)) #defineNFCONT_REG __REG(ELFIN_NAND_BASE+NFCONT_OFFSET) #define__REG(x) (*((volatileu32*)(x))) #defineELFIN_NAND_BASE 0x70200000 #defineNFCONT_OFFSET 0x04 NFCONT_REG=(*( (volatileu32*) (0x70200004) )) NFCONT0x70200004 讀/寫NANDFlash控制寄存器 [0]1:NANDFlash控制器使能 */ NAND_ENABLE_CE();
/* #defineNFCMD_REG __REG(ELFIN_NAND_BASE+NFCMMD_OFFSET) #defineELFIN_NAND_BASE 0x70200000 #defineNFCMMD_OFFSET 0x08 NFCMD_REG=(*( (volatileu32*) (0x70200008) )) NFCMMD 0x70200008 NANDFlash命令設置寄存器0 #defineNAND_CMD_READID 0x90
*/ NFCMD_REG=NAND_CMD_READID; * #defineNFADDR_REG __REG(ELFIN_NAND_BASE+NFADDR_OFFSET) #defineELFIN_NAND_BASE 0x70200000 #defineNFADDR_OFFSET 0x0C NFADDR_REG =(*( (volatileu32*) (0x7020000C) )) NFADDR0x7020000C NANDFlash地址設置寄存器 */ NFADDR_REG= 0x00;
/* #define NFDATA8_REG __REGb(ELFIN_NAND_BASE+NFDATA_OFFSET) #define__REGb(x) (*(vu_char*)(x)) NFDATA8_REG = (*( (vu_char*) (0x70200010) )) NFDATA0x70200010 讀/寫NANDFlash數據寄存器 NANDFlash 讀/燒寫數據值用於I/O */ /*waitforawhile*/ for(i=0;i<200;i++); id=NFDATA8_REG; id=NFDATA8_REG; if(id>0x80) large_block=1; if(id ==0xd5) large_block=2;
/*readNANDBlock. *128KB->240KBbecauseofU-Bootsizeincrease.byscsuh *So,read0x3c000bytesnot0x20000(128KB). */ /* #define CONFIG_SYS_PHY_UBOOT_BASE (CONFIG_SYS_SDRAM_BASE+0x07e00000) #define CONFIG_SYS_SDRAM_BASE 0x50000000 CONFIG_SYS_PHY_UBOOT_BASE= 0x57e00000 0x3c000 = 1M */ returnnandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE,0x3c000,large_block); } #endif
修改u-boot-2010.03/cpu/arm1176/Makefile,在COBJS = cpu.o后面加nand_cp.o
COBJS = cpu.o nand_cp.o
修改u-boot-2010.03/board/samsung/smdk6410/u-boot-nand.lds,添加nand_cp.o 如下:
{ cpu/arm1176/start.o (.text) cpu/arm1176/s3c64xx/cpu_init.o (.text) board/samsung/smdk6410/lowlevel_init.o (.text) cpu/arm1176/nand_cp.o(.text) lib_arm/board.o (.text) *(.text) }
修改u-boot-2010.03/cpu/arm1176/u-boot.lds,添加nand_cp.o,如下:
{ cpu/arm1176/start.o(.text) cpu/arm1176/s3c64xx/cpu_init.o (.text) board/samsung/smdk6410/lowlevel_init.o (.text) cpu/arm1176/nand_cp.o(.text) lib_arm/board.o (.text) *(.text) }
進入u-boot-2010.03/nand_spl/board/samsung,復制一個smdk6410,修改Makefile,作如下修改:
COBJS =nand_boot.onand_ecc.os3c64xx.onand_cp.o
在下面代碼
#fromSoCdirectory $(obj)cpu_init.S: @rm-f$@ @ln-s$(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S$@
之后添加
$(obj)nand_cp.c: @rm-f$@ @ln-s$(TOPDIR)/cpu/arm1176/nand_cp.c$@
修改u-boot-2010.03/board/samsung/smdk6410/lowlevel_init.S,修改/*LEDononly#8*/LED燈的測試代碼,將所有燈點亮,修改為:
/* LED on only #8 */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0001111 str r1, [r0, #GPMCON_OFFSET] ldr r1, 0x000aaa str r1, [r0, #GPNPUD_OFFSET] ldr r1, =0x0000 str r1, [r0, #GPNDAT_OFFSET]
配置,編譯,生成u-boot.bin,下到開發板上如下所示:
U-Boot 2010.03 ( 8��月 04 2012 - 21:49:40) for SMDK6410 CPU: S3C6400@533MHz Fclk = 533MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode) Board: SMDK6410 DRAM: 256 MB Flash: 0 kB NAND: No oob scheme define for oobsize 32
2048 MiB *** Warning - bad CRC, using default environment In:serial
Out:serial
Err:serial
Net:cs8900
Hit any key to stop autoboot: 0 板子上的4盞LED全亮!
這就完成了u-boot移植的第一步。
網卡DM9000移植:
在u-boot-2010.03/include/configs/smdk6410.h中將CS8900的宏定義注釋掉:
//#define CONFIG_NET_MULTI //#define CONFIG_CS8900 /*wehaveaCS8900on-board*/ //#define CONFIG_CS8900_BASE 0x18800300 //#define CONFIG_CS8900_BUS16 /*followthe Linuxdriver*/
然后添加DM9000網卡的宏定義:
#defineCONFIG_NET_MULTI 1 #defineCONFIG_DM9000_NO_SROM 1 #defineCONFIG_dm9000 #defineCONFIG_DRIVER_DM9000 1 #defineCONFIG_DM9000_BASE 0x18800300 #defineDM9000_IO CONFIG_DM9000_BASE #defineDM9000_DATA (CONFIG_DM9000_BASE+4) #defineCONFIG_DM9000_USE_16BIT #defineCONFIG_ETHADDR 00:40:5c:26:0a:5b #defineCONFIG_NETMASK 255.255.255.0 #defineCONFIG_IPADDR 192.168.1.20 #defineCONFIG_SERVERIP 192.168.1.10 #defineCONFIG_GATEWAYIP 192.168.1.1
//#define CONFIG_DM9000_DEBUG
上面的IP和網關、子網掩碼等根據自己的具體情況進行修改。接着打開u-boot-2010.03/net/eth.c,並且進入到函數inteth_initialize(bd_t*bis)中,在:
#ifdefined(CONFIG_DB64460)|| defined(CONFIG_P3Mx) mv6446x_eth_initialize(bis); #endif
后面添加:
同樣在u-boot-2010.03/net/net.c,
1.將
#defineARP_TIMEOUT 5000UL /*MillisecondsbeforetryingARPagain*/
修改為
#defineARP_TIMEOUT 5 /*MillisecondsbeforetryingARPagain*/
2. 將
if((t-NetArpWaitTimerStart)>ARP_TIMEOUT)
修改為
if((t-NetArpWaitTimerStart)>ARP_TIMEOUT*CONFIG_SYS_HZ
3. 將
NetSetTimeout(10000UL,PingTimeout);
修改為
NetSetTimeout(10*CONFIG_SYS_HZ,PingTimeout);
接着進入u-boot-2010.03/net/tftp.c,找到void TftpStart(void)函數,用#if0 #endif注釋掉下面的程序:
#if0 /* *Allowthe usertochooseTFTPblocksizeandtimeout *TFTPprotocolhasaminimaltimeoutof1second. */ if((ep=getenv("tftpblocksize"))!=NULL) TftpBlkSizeOption=simple_strtol(ep,NULL,10); if((ep=getenv("tftptimeout"))!=NULL) TftpTimeoutMSecs=simple_strtol(ep,NULL,10); if(TftpTimeoutMSecs<1000){ printf("TFTPtimeout(%ldms)toolow," "setminimum=1000ms\n", TftpTimeoutMSecs); TftpTimeoutMSecs=1000; } debug("TFTPblocksize=%i,timeout=%ldms\n",
TftpBlkSizeOption,TftpTimeoutMSecs); #endif
再編譯,下載,運行情況如下:
U-Boot 2010.03 ( 8��月 04 2012 - 21:49:40) for SMDK6410 CPU: S3C6400@533MHz Fclk = 533MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode) Board: SMDK6410 DRAM: 256 MB Flash: 0 kB NAND: No oob scheme define for oobsize 32
2048 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial
Net: dm9000 Hit any key to stop autoboot: 0
Nandflash讀寫:
nandflash的控制都是這個套路,因為這就是硬件協議,先使能芯片->發送命令->發送地址序列->讀或寫數據寄存器->判斷准備就緒狀態->禁止芯片,這是對nand flash操作的大體過程,根據發送命令的不同還有些區別。
進入u-boot-2010.03/driver/mtd/nand/,修改nand_ids.c,作如下修改:
//{"NAND 2GiB3,3V8-bit",0xD5,0,2048,0,LP_OPTIONS}, {"NAND2GiB3,3V8-bit", 0xD5,4096,2048,512*1024,LP_OPTIONS},
編譯下載,運行如下:
U-Boot 2010.03 ( 8��月 04 2012 - 21:49:40) for SMDK6410 CPU: S3C6400@533MHz Fclk = 533MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode) Board: SMDK6410 DRAM: 256 MB Flash: 0 kB NAND: raise: Signal # 8 caught raise: Signal # 8 caught raise: Signal # 8 caught 2048 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial
Net: dm9000 Hit any key to stop autoboot: 0
在NAND: 后面出現raise: Signal # 8 caught這些信息,雖然不影響運行,但是確實是一個BUG,花了一天的時間在網上查了一下,都是關於2410的,偶然在網上看到一位朋友也是碰到同樣的問題,修改跟移植2410的一樣處理,我試了,
修改/cpu/arm/arm1176/s3c64xx/timer.c,
imer_load_val用gd->timer_rate_hz替代;
timer_clk用gd->tbl替代;
timestamp用gd->timer_reset_value替代;
lastdec用gd->lastinc替代。
編譯的時候出現gd_t這個結構體根本就沒有timer_rate_hz這幾個成員變量,可能是版本的原因,在論壇上求助說修改lib_arm/eabi_compact.c,直接將printf("raise: Signal # %d caught\n", signum);注釋掉,至今我是這樣解決的,不影響啟動。修改后啟動如下:
U-Boot 2010.03 ( 8��月 04 2012 - 21:49:40) for SMDK6410 CPU: S3C6400@533MHz Fclk = 533MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode) Board: SMDK6410 DRAM: 256 MB Flash: 0 kB NAND: 2048 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial
Net: dm9000 Hit any key to stop autoboot: 0
這下正常了!
添加自己的命令:
boot有許多指令,nandinfo,set 等等。現在我們來給u-boot添加我們想要的指令。
U-Boot的每一個命令都是通過U_Boot_CMD宏定義的。這個宏在include/command.h頭文件中定義,每一個命令定義一個cmd_tbl_t結構體。
這樣每一個U-Boot命令有一個結構體來描述。結構體包含的成員變量:命令名稱、最大參數個數、重復數、命令執行函數、用法、幫助。
從控制台輸入的命令是由common/command.c中的程序解釋執行的。(這就是我要找的)find_cmd()負責匹配輸入的命令,從列表中找出對應的命令結構體。
基於U-Boot命令的基本框架,來分析一下簡單的icache操作命令,就可以知道添加新命令的方法。
(1)定義CACHE命令。在include/cmd_confdefs.h中定義了所有U-Boot命令的標志位。
如果有更多的命令,也要在這里添加定義。
(2)實現CACHE命令的操作函數。下面是common/cmd_cache.c文件中icache命令部分的代碼。
U-Boot的命令都是通過結構體__U_Boot_cmd_##name來描述的。根據U_Boot_CMD在include/command.h中的兩行定義可以明白。
還有,不要忘了在common/Makefile中添加編譯的目標文件。
(3)打開CONFIG_COMMANDS選項的命令標志位。這個程序文件開頭有#if語句需要預處理是否包含這個命令函數。CONFIG_COMMANDS選項在開發板的配置文件中定義。例如:SMDK2410平台在include/configs/smdk2410.h中有如下定義。
按照這3步,就可以添加新的U-Boot命令。
這下我們就知道怎樣添加自己的Uboot命令了,下面我以添加info命令為例:
1. 進入u-boot-2010.03/commom文件夾,新建cmd_info.c文件。代碼如下:
#include<common.h> #include<command.h> int do_info(cmd_tbl_t*cmdtp,intflag,intargc,char*constargv[]) { printf("u-boot is made by lixiaoming!\n"); return0; } U_BOOT_CMD(info,CONFIG_SYS_MAXARGS,1,do_info,"usageinfo", "helpinfo");
2. 然后在common/Makefile 中 的#command 添 加 如 下 內 容 :
COBJS-$(CONFIG_CMD_INFO)+=cmd_hello.o
3. 在u-boot-2010.03/include/config_cmd_default.h中添加CONFIG_CMD_INFO命令,同時也在config_cmd_all.c中定義
這下編譯,下載,運行進入uboot命令模式后輸入:info,就會顯示信息了;
SMDK6410# info u-boot is made by lixiaoming!
內核引導:
由於uboot只能引導uImage,因此需要把編譯成的zImage轉換成uImage,先進入u-boot根目錄下,把tools/下mkimage復制到主機的/bin目錄下,然后進入到linux-3.0.4/下輸入指令:make uImage。
#defineCONFIG_BOOTARGS "root=/dev/mtdblock2 rootfstype=yaffs2 console=ttySAC0,115200"
是在smdk6410.h里面。這要根據linux內核mach-ok6410.c中的:
staticstructmtd_partitionok6410_nand_part[]={ { .name ="Bootloader", .offset =0, .size =(1*SZ_1M), .mask_flags =MTD_CAP_NANDFLASH, }, {
.name ="Kernel", .offset =(1*SZ_1M), .size =(5*SZ_1M), .mask_flags =MTD_CAP_NANDFLASH, }, { .name ="User", .offset =(6*SZ_1M), .size =(120*SZ_1M), }, { .name ="FileSystem", .offset =MTDPART_OFS_APPEND, .size =MTDPART_SIZ_FULL, } };
上面主要是對MTD進行分區,可以自己分配,不過一定要把Uboot與內核結合起來。
到此,自己的6410開發板的Uboot基本移植成功,現在自己可以添加命令了,后面的就可以添加啟動后進入主菜單實現下載等功能的命令,在后面的幾天我也移植了Linux3.0.4內核到開發板上,成功運行,並移植支持yaff2文件系統的讀寫,再后面自己制作文件系統鏡像,成功運行完整的嵌入式系統!
在移植的過程中感謝網上朋友的無私分享,我也記錄一下自己的移植工程,與大家一起共同進步,有一天可以成為嵌入式牛人!
參照文章:
寧靜致遠的文章《基於OK6410的u-boot2010.03移植過程》 (http://wenku.baidu.com/view/ae78a00390c69ec3d5bb75ce.html?st=1)
懶惰人的懶惰事 (http://hi.baidu.com/shangyefeng/item/4df893ee978c5e245b2d646f)