移植u-boot.2012.04.01

/***************************************************

*u-boot版本:u-boot2012.04.01

*gcc版本:arm-linux-gcc-4.3.2

*服务器:ubuntu12.04

***************************************************/

一、建立单板
    在board/复制smdk2410文件夹为smdk2440文件夹
    在include/configs/将smdk2410.h  - >smdk2440.h
    
二、修改时钟
    1.进入smdk2440文件夹,修改函数board_early_init_f
      注释掉:
      //writel(0xFFFFFF, &clk_power->locktime);

       /* configure MPLL */
       //writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
      //       &clk_power->mpllcon);
    
    
    2.在start.S里面:
      /* FCLK:HCLK:PCLK = 1:2:4 */
      /* default FCLK is 400 MHz ! */
      /*2. 设置时钟 */
         ldr r0, =0x4c000014
         // mov r1, #0x03;     // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
         mov r1, #0x05;     // FCLK:HCLK:PCLK=1:4:8
         str r1, [r0]
        
         /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
         mrc p15, 0, r1, c1, c0, 0  /* 读出控制寄存器 */
         orr r1, r1, #0xc0000000   /* 设置为“asynchronous bus mode” */
         mcr p15, 0, r1, c1, c0, 0  /* 写入控制寄存器 */
        
        #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
        
         /* MPLLCON = S3C2440_MPLL_200MHZ */
         ldr r0, =0x4c000004
         ldr r1, =S3C2440_MPLL_400MHZ
         str r1, [r0]
        
         /* 启动ICACHE */
         mrc p15, 0, r0, c1, c0, 0 @ read control reg
         orr r0, r0, #(1<<12)
         mcr p15, 0, r0, c1, c0, 0   @ write it back
        #endif    /* CONFIG_S3C24X0 */
    
     3.  ③把lowlevel_init.S里面的lowlevel_init函数里面
         SMRDATA:
        .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
        .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
        .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
        .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
        .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
        .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
        .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
        .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
        .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
        .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
        .word 0x32
        .word 0x30
        .word 0x30
     替换为:
     SMRDATA:
         .long 0x22011110  //BWSCON
         .long 0x00000700  //BANKCON0
         .long 0x00000700  //BANKCON1
         .long 0x00000700  //BANKCON2
         .long 0x00000700  //BANKCON3  
         .long 0x00000700  //BANKCON4
         .long 0x00000700  //BANKCON5
         .long 0x00018005  //BANKCON6
         .long 0x00018005  //BANKCON7
         .long 0x008C04F4  // REFRESH
         .long 0x000000B1  //BANKSIZE
         .long 0x00000030  //MRSRB6
         .long 0x00000030  //MRSRB7
         
    4.$ vi boards.cfg
      在boards.cfg文件下复制65行,修改boards.cfg:
      仿照
      smdk2410                     arm         arm920t     -                   samsung        s3c24x0
      添加:
      smdk2440                     arm         arm920t     -                   samsung        s3c24x0
        5.完成以上三步,编译通过
        6.乱码,查看串口波特率的设置,发现在get_HCLK里没有定义CONFIG_S3C2440
        7.处理措施:include/configs/smdk2440.h:
           去掉CONFIG_S3C2410
           添加#define CONFIG_S3C2440
           编译,出现错误:
           s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
        8. 处理措施:舍弃nand,使用我们自己的代码init.c
            $ vi drivers/mtd/nand/Makefile     //从makefile看出依赖于哪个宏,而不是在makefile里面注释掉
        COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
        得知依赖的宏是CONFIG_NAND_S3C2410
        进入:include/configs/smdk2440.h  -->
        有:    /*
             * NAND configuration
             */
            #ifdef CONFIG_CMD_NAND
            #define CONFIG_NAND_S3C2410
            #define CONFIG_SYS_S3C2410_NAND_HWECC
            #define CONFIG_SYS_MAX_NAND_DEVICE      1
            #define CONFIG_SYS_NAND_BASE            0x4E000000
            #endif
        所以我们屏蔽掉CONFIG_CMD_NAND宏即可
    9.烧写
    
        下面是uboot输出:
        U-Boot 2012.04.01 (Jul 29 2013 - 20:26:01)
        
        CPUID: 32440001
        FCLK:      400 MHz
        HCLK:      100 MHz
        PCLK:       50 MHz
        DRAM:  64 MiB
        WARNING: Caches not enabled
        Flash: *** failed ***
        ### ERROR ### Please RESET the board ###   串口输出正确
        
        此时支持nor启动,但是不支持nand启动
        
/*##############################################################华丽分界线########################################################*/

修改UBOOT支持NAND启动
    1.1 去掉 "-pie"选项,减少代码大小
        grep "-pie" * -nR
              arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行
              如下:
              ifndef CONFIG_NAND_SPL
        #LDFLAGS_u-boot += -pie
        endif
    1.2  把init.c放入board/samsung/smdk2440目录,修改init.c文件主要是加上static , 修改Makefile
         修改CONFIG_SYS_TEXT_BASE为0x33f80000    //0x34000000-33f80000 =512k,对于uboot足够

    1.3  修改start.S
            ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)
        bic    sp, sp, #7 /* 8-byte alignment for ABI compliance */
    
    
        bl nand_init_ll
        mov r0, #0          //src_addr
        //ldr r1, =_start
        ldr r1,_TEXT_BASE   //地址固定   dest_addr
        
        //ldr r2, =__bss_start   //CONFIG_SYS_TEXT_BASE
        //sub r2, r2, r1
        //以上两条在这里是
        ldr r2,_bss_start_ofs      //len
    
    
        bl copy_code_to_sdram
        bl clear_bss
    
        ldr pc,= call_board_init_f
    
        /* Set stackpointer in internal RAM to call board_init_f */
        call_board_init_f:
            ldr    r0,=0x00000000
            bl    board_init_f   //会调用重定位
    
         =============================================================
             
             //第一个参数由board_init_f传回来,存在r0里面   < ------------------------                         -
             ldr r1,_TEXT_BASE                                                      |
             bl     board_init_r    //调用第二阶段                                  |
                                                                                            |
        修改init.c                                                                      |
                                                |
            __bss_end__名字有点差别                                                    |
                                                                                                |            
    1.4 修改board_init_f, 把relocate_code去掉                                               |
        //relocate_code(addr_sp, id, addr);                                                 |
        删掉start.S里面相关代码,然后下面就执行第二阶段代码,实质上调用board_init_r         |
    1.5 修改board_init_r ,函数原型是void board_init_r(gd_t *id, ulong dest_addr)           |         
        参数:r0 = 链接地址                                                                 |
              r1 = id  (可以使用board_init_f返回得到)   -----------------------------------
         相应的在board_init_f,把void变为snsigned int
         并在最后加上:
         return (unsigned int*)id;
         
    1.6  修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
        find -name "u-boot.lds"
              ./arch/arm/cpu/u-boot.lds:      
              board/samsung/smdk2440/libsmdk2440.o (.text)
          1.7  编译报错
              board.c:259: error: conflicting types for 'board_init_f'
        previous declaration of 'board_init_f' was here
            /work/tmp/u-boot-2012.04.01/include/common.h:276: error:
    1.8  修改:/include/Common.h
        /* arch/$(ARCH)/lib/board.c */
        unsigned int    board_init_f  (ulong);
        void    board_init_r  (gd_t *, ulong);
    1.9  编译
        #make distclean
        #make smdk2440_config
        #make
    1.10  结果 ok。
          注意:期间可能会发生各种乱七八糟的错误,尽量多执行make distclean然后再重新编译
    
    2.0   地址映射不对
          修改board_init_f函数:
              //addr -= gd->mon_len;
        //addr &= ~(4096 - 1);
        addr = CONFIG_SYS_TEXT_BASE;  //or addr = _TEXT_BASE      
        
    此时发现u-boot.bin有40多k,包括bss段有70多k,那么我们设定的CONFIG_SYS_TEXT_BASE为0x33f80000到34000000有512k
    所以这里还是不够的,那么我们在这里把CONFIG_SYS_TEXT_BASE设定为0x33f00000,预留1M,足够
    .globl _bss_end_ofs   //start.S 是程序本身的大小,可以在反汇编里面查看到大小
        _bss_end_ofs:
            .word __bss_end__ - _start
            
    乱码:
    因为CONFIG_CMD_NAND没有屏蔽掉
    
    报错:/work/tmp/u-boot-2012.04.01/fs/yaffs2/yaffscfg.c:210: undefined reference to `nand_info'
    处理:去掉#define CONFIG_YAFFS2    -- 》 在smdk2440.h里面
    
    打印信息:说明支持NAND FLASH
    
    U-Boot 2012.04.01 (Jul 26 2015 - 16:02:34)
    
    CPUID: 32440001
    FCLK:      400 MHz
    HCLK:      100 MHz
    PCLK:       50 MHz
    DRAM:  64 MiB
    
    以上支持nand启动,但是并不是支持nand读写操作
/*######################################################华丽分界线####################################################*/            
            
修改UBOOT支持NOR FLASH
    此时,uboot会打印如下内容:    
        Flash: *** failed ***
        ### ERROR ### Please RESET the board ###   串口输出正确
    搜索“Flash”看源码知:
        board_init_r函数里面有:  //arch/arm/lib/board.c
        # ifdef CONFIG_SYS_FLASH_CHECKSUM
        。。。
        else {
        puts(failed);
        hang();
    }而
    hang()
        void hang(void)
        {
        puts("### ERROR ### Please RESET the board ### ");
        for (;;);
        }
    说明,由于没有定义CONFIG_SYS_FLASH_CHECKSUM,导致,在hang()里面死循环
    修改为:
    else {
          puts("0 KB ");   //屏蔽掉hang()函数
          //puts(failed);
          //hang();
         }
        
    怎么样可以让nand里面识别出 nor flash ?
    flash_init()里面有:
    if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))   //先使用flash_detect_legacy老版本来检测
        //#ifdef CONFIG_FLASH_CFI_LEGACY使用这个宏来决定使用哪一个
            flash_get_size(cfi_flash_bank_addr(i), i);   //新方法
            
    flash_detect_legacy里面调用
        flash_read_jedec_ids(info);得到ID信息
        jedec_flash_match  //匹配ID信息
            遍历jedec_table数组,找到对应芯片

我们使用的芯片是MX29LV160DB,但是uboot里面没有,而有相近的AM29LV040B,这是需要借助数据手册仿写一个
MX29LV160DB特性有:
大小:2M
位数:16位
扇区数目:4个

已经有的配置:    
{
        .mfr_id        = (u16)MX_MANUFACT,
        .dev_id        = MX29LV040,
        .name        = "MXIC MX29LV040",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },


以上各种参数说明:
struct amd_flash_info {
    const __u16 mfr_id;
    const __u16 dev_id;
    const char *name;
    const int DevSize;
    const int NumEraseRegions;
    const int CmdSet;
    const __u8 uaddr[4];        /* unlock addrs for 8, 16, 32, 64 */
    const ulong regions[6];
};

在上面    flash_get_size()函数里面有一句:
if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {
                    printf("ERROR: too many flash sectors ");
                    break;
                }
。。。
for (i = 0; i < num_erase_regions; i++) {                       //搜索num_erase_regions可知扇区最多有4种
            if (i > NUM_ERASE_REGIONS) {
                printf ("%d erase regions found, only %d used ",
                    num_erase_regions, NUM_ERASE_REGIONS);
                break;
            }
                

搜索CONFIG_SYS_MAX_FLASH_SECT可以知道:
#define CONFIG_SYS_MAX_FLASH_SECT    (19)  扇区数量最大19个            

在目录drivers/mtd/jedec_flash.c
最终修改为:
        
{
        .mfr_id        = (u16)MX_MANUFACT,     //厂家ID
        .dev_id        = 0x2249,        //设备ID
        .name        = "MXIC MX29LV160DB",     //名字
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */    //unlock addr
        },
        .DevSize    = SIZE_2MiB,           //size
        .CmdSet        = P_ID_AMD_STD,          //命令类型
        .NumEraseRegions= 4,                    //可擦除扇区数目,这里是4个
        .regions    = {
            ERASEINFO(16*1024,1),          //下面是具体的扇区列表
            ERASEINFO(8*1024,2),
            ERASEINFO(32*1024,1),
            ERASEINFO(64*1024,31)
        }
}
注意上面信息应该加载endif后面,即宏开关的控制    

打印信息:
U-Boot 2012.04.01 (Aug 01 2015 - 20:48:21)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB

搜索CPUID,发现,程序只执行到board_init_f里面init_sequence的print_cpuinfo/* display cpu info (and speed) */

添加打印信息board.c里面
#define _DEBUG    1                  //add by hulig
#define DEBUG    1

最终ok
修改栈:

在start.S里面添加宏:

.globl base_sp   //定义
base_sp:
    .long 0
    
在board.c里面加上         //声明
extern ulong base_sp;

然后board_init_f 最后调用   //使用
base_sp = addr_sp;

在start.S里面调用board_init_r之前重新设置栈
ldr sp,base_sp


编译通过。
打印信息:

U-Boot 2012.04.01 (Aug 03 2015 - 21:24:22)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: 2 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0
SMDK2410 #

            
/*#################################################我是分界线###############################################*/            

 修改UBOOT支持NAND FLASH
    修改:include/configs/smdk2440.h: #define CONFIG_CMD_NAND
    报错:
    s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
    原因:    writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE,
    
    寄存器指向的是s3c2410的寄存器,所以要使用nand,还需要重新设置寄存器        
    
    把driversmtd ands3c2410_nand.c复制为s3c2440_nand.c ,把2410都替换成2440并修改Makefile
    COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o       ==>
    COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
    
    同时需要修改配置文件smdk2440.h
        /*
     * NAND configuration
     */
    #ifdef CONFIG_CMD_NAND
    #define CONFIG_NAND_S3C2410        == >#define CONFIG_NAND_S3C2440
    #define CONFIG_SYS_S3C2410_NAND_HWECC   ==>#define CONFIG_SYS_S3C2440_NAND_HWECC
           
分析过程:
nand_init
 nand_init_chip
  board_nand_init
   设置nand_chip结构体, 提供底层的操作函数
  nand_scan
   nand_scan_ident
    nand_set_defaults
     chip->select_chip = nand_select_chip;  //上面chip->select_chip为空,就使用这里默认的函数,但是这里选中后没做任何事
     chip->cmdfunc = nand_command;  //
     chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
     
    nand_get_flash_type
     chip->select_chip
     chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
       nand_command()  // 即可以用来发命令,也可以用来发列地址(页内地址)、行地址(哪一页)  nand_base.c
        chip->cmd_ctrl
          s3c2440_hwcontrol
        
     chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
     *maf_id = chip->read_byte(mtd);
     *dev_id = chip->read_byte(mtd);
            

分析:  
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
/*ctrl : 表示做什么,选中/取消片选还是发命令或者发地址
 *cmd  :命令值或地址值
 *



修改:
1.    ./drivers/mtd/nand/s3c2440_nand.c
    int board_nand_init(struct nand_chip *nand)
    {
            u_int32_t cfg;
            u_int8_t tacls, twrph0, twrph1;
            struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
            struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
    
            debug("board_nand_init() ");
    
            writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);
    
            /* initialize hardware */
    #if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
            tacls  = CONFIG_S3C24XX_TACLS;
            twrph0 = CONFIG_S3C24XX_TWRPH0;
            twrph1 =  CONFIG_S3C24XX_TWRPH1;
    #else
            tacls = 4;
            twrph0 = 8;
            twrph1 = 8;
    #endif
    
    #if 0               // 屏蔽掉
            cfg = S3C2440_NFCONF_EN;
            cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
            cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
            cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
    #endif  
    
            cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);  //使用这个参数
            
            writel(cfg, &nand_reg->nfconf);
    
            /* initialize nand_chip data structure */
            nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
            nand->IO_ADDR_W = (void *)&nand_reg->nfdata;
    
            nand->select_chip = NULL;             //这里我们不用,s3c2440_hwcontrol这个里面设置片选
                              //这里需要我们自己来写
    ...
    }
            
            
2.    修改片选函数drivers/mtd/nand/s3c2440_nand.c      里面s3c2440_hwcontrol函数        

                /*add by fanlin*/
                if (ctrl & NAND_NCE)
                        writel(readl(&nand->nfcont) & ~(1<<1),   //以前拷贝的是2410里面的,这里的片选控制有区别
                               &nand->nfcont);
                else
                        writel(readl(&nand->nfcont) | (1<<1),
                               &nand->nfcont);            
            
    这个函数我们都不用,片选重新写
    
//ctrl : 表示做什么,选中/取消片选还是发命令或者发地址
//dat  :命令值或地址值     根据nand_command重写
static void s3c2440_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
    
    struct s3c2440_nand *nand = s3c2440_get_base_nand();

    if(ctrl & NAND_CLE)
    {
    /*发命令*/
    writeb(dat,&nand->nfcmd);
    }
    else if(ctrl & NAND_ALE)
    {
    /*发地址*/
    writeb(dat,&nand->nfaddr);
    }
}    
    

3.    使能函数还有

    /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
    NFCONT = (1<<4)|(1<<1)|(1<<0);    
写成:

        /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
        writel((1<<4)|(1<<1)|(1<<0),&nand_reg->nfcont);

放在:
            cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);  //使用这个参数
            
            writel(cfg, &nand_reg->nfconf);
            这两句后面
            
            
4.    选中函数nand->select_chip = s3c2440_nand_select;

参考nand_set_defaults   在nand_base.c里面
     chip->select_chip = nand_select_chip;             
    static void nand_select_chip(struct mtd_info *mtd, int chipnr)
    {
        struct nand_chip *chip = mtd->priv;
    
        switch (chipnr) {
        case -1:    //不选
            chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
            break;
        case 0:   //选中
            break;
    
        default:
            BUG();
        }
    }
    
我们的代码写成:放在s3c2440_nand.c里面,修改函数名字

static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    
    switch (chipnr) {
    case -1:
        nand->nfcont |= (1<<1);
        break;
    case 0:
        nand->nfcont &= ~(1<<1);
        break;
    
    default:
        BUG();
    }
}

打印信息如下:

U-Boot 2012.04.01 (Aug 06 2015 - 22:00:36)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: 2 MiB
NAND:  256 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0
SMDK2410 #

说明nand flash已经识别了
                
/****************************************我是分界线*****************************************/            
            
修改u-boot支持DM9000网卡
    搜索dm9000,发现在/drivers/net里面,查看Makefile有:
    COBJS-$(CONFIG_CS8900) += cs8900.o
    COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o
    
    所以需要定义CONFIG_DRIVER_DM9000这个宏,而应该去掉cs9000,在smdk2440.h里面
    #if 0
    #define CONFIG_CS8900           /* we have a CS8900 on-board */
    #define CONFIG_CS8900_BASE      0x19000300
    #define CONFIG_CS8900_BUS16     /* the Linux driver does accesses as shorts */
    #else
    #define CONFIG_DRIVER_DM9000
    #endif            
            
    报错:
    dm9000x.c:156: error: 'DM9000_DATA' undeclared (first use in this function)
    查找DM9000_DATA,发现其他用这个不仅仅是定义CONFIG_DRIVER_DM9000
    如:
    /* Hardware drivers */
    /* DM9000 */
    #define CONFIG_NET_RETRY_COUNT          20
    #define CONFIG_DRIVER_DM9000            1
    #define CONFIG_DM9000_BASE              0x2c000000   //这个值一定不会适合我们的开发板
    #define DM9000_IO                       CONFIG_DM9000_BASE
    #define DM9000_DATA                     (CONFIG_DM9000_BASE + 0x400)
    #define CONFIG_DM9000_USE_16BIT         1
    #define CONFIG_DM9000_NO_SROM           1
    #undef  CONFIG_DM9000_DEBUG        
    
    以上参数应该只是定义了,但是值都不适用,怎么修改呢?
    1.设置内存控制器(时序,位宽)   这个在设置sdram里面说明
    2.确定访问地址
    
    根据三星手册,知道,网卡在内存地址范围是0x20000000 ~ 0x28000000
    最终修改为:
    
    #if 0
    #define CONFIG_CS8900           /* we have a CS8900 on-board */
    #define CONFIG_CS8900_BASE      0x19000300
    #define CONFIG_CS8900_BUS16     /* the Linux driver does accesses as shorts */
    #else
    #define CONFIG_DRIVER_DM9000
    #define CONFIG_DM9000_BASE              0x20000000
    #define DM9000_IO                       CONFIG_DM9000_BASE
    #define DM9000_DATA                     (CONFIG_DM9000_BASE + 4)
    #endif
        
    编译通过,烧写后打印信息如下:
    Net:   No ethernet found.
    
    
        
调用过程:
board.c
    eth_initialize
        board_eth_init
            cs8900_initialize    //这里是cs8900的初始化函数,在smdk2410.c里面

修改:
    参看别的单板怎么使用:
    grep "dm9000_initialize" * -nR
    其中格式为;
    board/vpac270/vpac270.c:141:    return dm9000_initialize(bis);
    
    所以:
    修改smdk2410.c  里面board_eth_init函数:
    
    #ifdef CONFIG_CS8900
    rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
    #endif
    #ifdef CONFIG_DRIVER_DM9000
            rc = dm9000_initialize(bis);
    #endif        
            
烧写识别了dm9000

输入print,输出ip信息,要ping通,需要先设置ip地址
set ipaddr 192.168.1.9
set serverip 192.168.1.17
注意:不要使用save命令

现在可以ping通服务器了

以上移植支持网卡,也支持烧写,还可以启动内核:



/***************************************分界线*****************************************/            
修改默认参数:

搜索default environment
在Env_common.c函数里面:
    default_environment结构体
    default_environment结构体定义在env_common.c里面
    
其中有:
    #ifdef    CONFIG_BOOTARGS
        "bootargs="    CONFIG_BOOTARGS            ""
    #endif
    
    这里CONFIG_BOOTARGS没有定义,bootargs是传给内核的环境变量,在smdk2440.h里面定义CONFIG_BOOTARGS
    #define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"
    
    此外设置bootcmd参数:
    #define CONFIG_BOOTCOMMAND "nand read 30000000 0x30008000 0x200000;bootm 30000000"
    假设从0x30008000读2M到30000000
    
    设置ip
    #define CONFIG_NETMASK        255.255.255.0
    #define CONFIG_IPADDR        192.168.1.10
    #define CONFIG_SERVERIP        192.168.1.17
    #define CONFIG_ETHADDR        00:0c:29:45:c4:c3    
    
    
    
裁剪:
    在配置文件smdk2440.h里面屏蔽掉不用的项;
    1.USB support (currently only works with D-cache off)
    2.RTC
    3.Boottp
    4.文件系统
    
    
修改默认分区:
    打印出来的分区信息:
    0x00000000-0x00040000 : "bootloader"     //256k
    0x00040000-0x00060000 : "params"    //
    0x00060000-0x00260000 : "kernel"    //
    0x00260000-0x10000000 : "root"


原来的环境变量的配置:
    #define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x070000)
    #define CONFIG_ENV_IS_IN_FLASH
    #define CONFIG_ENV_SIZE            0x10000
    /* allow to overwrite serial and ethaddr */
    #define CONFIG_ENV_OVERWRITE    
    
上面说过不要用save命令保存环境变量设置,目的是防止flash被破坏:
    查看save命令帮助信息,知道saveenv,搜索saveenv    
    或者在SI里面搜索可得,在common目录下看Makefile,知道依赖上面宏
    Env_nand.c (common):int saveenv(void)
    
    makefile里面有:
    COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o        
    可知需要CONFIG_ENV_IS_IN_NAND    
    
    不光如此,还需要知道起始地址和大小    
    打开env_nand.c,里面有CONFIG_ENV_SIZE和CONFIG_ENV_OFFSET    
    
    上面的还不够,还需要擦除长度
    nand_erase_options.length = CONFIG_ENV_RANGE;
    
    即需要定义CONFIG_ENV_RANGE,设为CONFIG_ENV_SIZE    
            
综上所知设置为:
    #if 0
    #define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x070000)
    #define CONFIG_ENV_IS_IN_FLASH
    #define CONFIG_ENV_SIZE            0x10000
    /* allow to overwrite serial and ethaddr */
    #define CONFIG_ENV_OVERWRITE
    #endif
    #define CONFIG_ENV_IS_IN_NAND
    #define CONFIG_ENV_OFFSET 0x00040000
    #define CONFIG_ENV_SIZE 0x20000
    #define CONFIG_ENV_RANGE CONFIG_ENV_SIZE            
            
            
分区:    ※uboot里面的分区不会作为参数传到内核里面,而是作为一些字符串代替一些数字方便操作uboot而已
    这里使用mtdpart命令不被识别,搜索common/下的makefile后发现需要定义            
    COBJS-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o    
    所以需要定义CONFIG_CMD_MTDPARTS        
        
看看别人怎么做:搜索mtdpart_init()    
在board.c里面调用mtdpart_init()    

参考别的单板
#define MTDIDS_DEFAULT    "nor0=TQM8xxL-0"    哪一个设备

#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot),"       
                    "128k(dtb),"        
                    "1664k(kernel),"    
                    "2m(rootfs),"        
                    "4m(data)"
        
        
改写如下:
#define CONFIG_CMD_MTDPARTS
#define MTDIDS_DEFAULT        "nand0=jz2440-0"

#define MTDPARTS_DEFAULT "mtdparts=jz2440-0:256k(u-boot),"    
                    "128k(params),"        
                    "2m(kernel),"        
                    "-(rootfs)"        
                        
以上编译出错:
    /common/cmd_mtdparts.c:306: undefined reference to `get_mtd_device_nm'    
    查看代码发现get_mtd_device_nm在drivers/mtd里面的mtdcore.c里面实现了
    再查看drivers/mtd下makefile:
    COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
    也就是要定义CONFIG_MTD_DEVICE宏,在smdk2440里面定义这个宏,重新编译
    
    烧写打印信息如下:
    mtdparts variable not set, see 'help mtdparts'
    no partitions defined
    
    defaults:
    mtdids  : nand0=jz2440-0
    mtdparts: mtdparts=jz2440-0:256k(u-boot),128k(params),2m(kernel),-(rootfs)
    
    
    
执行help mtdparts
    Usage:
    mtdparts
        - list partition table    //列出所有分区
    mtdparts delall               删除所有分区
        - delete all partitions
    mtdparts del part-id           //删除分区
        - delete partition (e.g. part-id = nand0,1)
    mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]
        - add partition           //添加分区
    mtdparts default             //默认分区
        - reset partition table to defaults
    
    从上面看出,可能是mtdparts default 没有被执行,看看有没有参考的
    在common/cmd_mtdparts.c有mtdparts default如下:
    
    U_BOOT_CMD(
    mtdparts,    6,    0,    do_mtdparts,
    "define flash/nand partitions",
    " "
    可知执行命令是    
    do_mtdparts
        setenv("mtdparts", (char *)mtdparts_default);  
    其中mtdparts_default
        #if defined(MTDPARTS_DEFAULT)
        static const char *const mtdparts_default = MTDPARTS_DEFAULT;
        #else
        static const char *const mtdparts_default = NULL;
        #endif    
    那么我们定义MTDPARTS_DEFAULT这个宏试试看    
        
正确的办法是:
    在cmd_mtdparts里面,函数do_mtdparts有:
    if (argc == 2) {        
        if (strcmp(argv[1], "default") == 0) {      //如果有参数default,比较,我们使用mtdpart命令不带参数,所以下面mtdparts_init()不会被执行
            setenv("mtdids", (char *)mtdids_default);   //写入默认参数
            setenv("mtdparts", (char *)mtdparts_default);
            setenv("partition", NULL);

            mtdparts_init();               //执行初始化函数
            return 0;
        } else if (strcmp(argv[1], "delall") == 0) {        
        
把default下面函数放在判断意外,无条件执行:

    setenv("mtdids", (char *)mtdids_default);   //写入默认参数
    setenv("mtdparts", (char *)mtdparts_default);
    setenv("partition", NULL);
    mtdparts_init();

    if (argc == 2) {        
        if (strcmp(argv[1], "default") == 0) {      //如果有参数default,比较,我们使用mtdpart命令不带参数,所以下面mtdparts_init()不会被执行
            //setenv("mtdids", (char *)mtdids_default);   //写入默认参数
            //setenv("mtdparts", (char *)mtdparts_default);
            //setenv("partition", NULL);

            //mtdparts_init();               //执行初始化函数
            return 0;
        } else if (strcmp(argv[1], "delall") == 0) {
        
    这样就可以了。
    
注意:这个办法有缺点,就是每次都要先执行mtdpart命令,然后才能使用分区。

    
另一个办法是在mian_loop里面先执行:
    run_command("mtdparts default",0); //这个办法很凑巧
            
参看100ask的u-boot-1.1.6里面关于这个的做法:
在main.c里面的main_loop有:
    #ifdef CONFIG_JFFS2_CMDLINE
        extern int mtdparts_init(void);
        if (!getenv("mtdparts"))
        {
            run_command("mtdparts default", 0);
        }
        else
        {
            mtdparts_init();
        }
    #endif

我们使用:
    #ifdef CONFIG_CMD_MTDPARTS
        extern int mtdparts_init(void);
        if (!getenv("mtdparts"))
        {
            run_command("mtdparts default", 0);
        }
        else
        {
            mtdparts_init();
        }
    #endif

    //可以不用每次都输入mtdpart命令后才可以使用分区信息
    
            
            修改struct mtd_device *current_mtd_dev = NULL;  ==1的时候
            
            mtdparts variable not set, see 'help mtdparts'
            no partitions defined
            data abort
            pc : [<33f0578c>]          lr : [<33f071ac>]
            sp : 33affdc8  ip : 0000000f     fp : 00000000
            r10: 33f35510  r9 : 33b03060     r8 : 33afff64
            r7 : 33b03100  r6 : 33b03100     r5 : 33f350f8  r4 : 33f32e28
            r3 : 33f350f8  r2 : 50000010     r1 : 00000000  r0 : 00000001
            Flags: nzCv  IRQs off  FIQs off  Mode SVC_32
            Resetting CPU ...
            
            resetting ...
            
            
            U-Boot 2012.04.01 (Aug 08 2015 - 22:43:07)
            
            CPUID: 32440001
            FCLK:      400 MHz
            HCLK:      100 MHz
            PCLK:       50 MHz
            DRAM:  64 MiB
            WARNING: Caches not enabled
            Flash: 2 MiB
            NAND:  256 MiB
            NAND read from offset 40000 failed -74
            *** Warning - readenv() failed, using default environment
            
            In:    serial
            Out:   serial
            Err:   serial
            Net:   dm9000
            Hit any key to stop autoboot:  0         
        
        
/***************************************分界线********************************************/        
支持yaffs2文件的烧写

tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 xx

set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

烧写yaffs
tftp 30000000 fs_mini_mdev.yaffs2   //fs_qtopia.yaffs2
nand erase.part root
nand write.yaffs 30000000 260000 2f76b40


烧写内核:
tftp 30000000 uImage_4.3
nand erase.part kernel
nand write.jffs2 30000000 kernel 1c359c

更新uboot:
tftp 30000000 u_boot_new.bin;protect off all;erase 0 3ffff;cp.b 30000000 0 40000

1.在cmd_nand.c里面,要用yaffs选项,需要定义CONFIG_CMD_NAND_YAFFS
重新烧写发现只烧写了一页,最终问题点出现在nand_write_skip_bad这个函数里面
ops.len = pagesize;
            ops.ooblen = nand->oobsize;
            ops.mode = MTD_OOB_AUTO;     //这里应该改成MTD_OOB_RAW
            ops.ooboffs = 0;

            pages = write_size / pagesize_oob;
            for (page = 0; page < pages; page++) {
                WATCHDOG_RESET();

                ops.datbuf = p_buffer;
                ops.oobbuf = ops.datbuf + pagesize;

                rval = nand->write_oob(nand, offset, &ops);
                if (!rval)  //fanlin 非0 才会错误
                    break;



去掉“!”即可。


补丁制作过程:
1.make distclean
2.rm u-boot.lds
3.cd ..
4.rm u-boot-2012.xx  u-boot-2012.xx_ok
5.解压原来下载的源码tar xjf u-boot-2012.xx.tar
6.制作补丁:
    diff -urN u-boot-2012.04.01 u-boot-2012.04.01_ok > u-boot-2012.04.01.patch

补丁制作ok。


重要:
1、
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############T T *** ERROR: Cannot umount
         
解决:
    修改NFS.C里面的#define NFS_TIMEOUT (10*2000UL)   延时设长一点就可以了。
        
          
2、

挂接成功,但是Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
 
 可能原因是uboot对yaffs不好,可以换成1.1.6实验,u-boot-1.1.6可以启动当前内核,说明u-boot-2012.04.01对yaffs不够好
 
 修改uboot
 cmd_nand.c
     nand_write_skip_bad
         if (!need_skip && !(flags & WITH_DROP_FFS)
         修改为:
         if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB))


        
       

原文地址:https://www.cnblogs.com/hulig7/p/4678582.html