• 移植属于自己的6410开发板的UBoot


    学习了几个月的关于嵌入式相关的知识,之前一直觉得自己能力不够,去研究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

  • 相关阅读:
    sql查询
    PHP常用的设计模式
    PHP内存管理和垃圾回收机制
    记一次面试
    获取py文件函数名及动态调用
    正确解决 mysql 导出文件 分隔符 问题
    解决ValueError: cannot convert float NaN to integer
    Python ---接口返回值中文编码问题
    pandas python 读取大文件
    【neo4J】后台关闭后,前端还能打开视图
  • 原文地址:https://www.cnblogs.com/lixiaoming90/p/2633151.html
Copyright © 2020-2023  润新知