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

*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 ###\n");
        for (;;);
        }
    说明,由于没有定义CONFIG_SYS_FLASH_CHECKSUM,导致,在hang()里面死循环
    修改为:
    else {
          puts("0 KB\n\r");   //屏蔽掉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\n");
                    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\n",
                    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,还需要重新设置寄存器        
    
    把drivers\mtd\nand\s3c2410_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()\n");
    
            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            "\0"
    #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",
    "\n"
    可知执行命令是    
    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))

移植u-boot.2012.04.01的更多相关文章

  1. z-index总结【转载http://www.cnblogs.com/mind/archive/2012/04/01/2198995.html】

    元素位置重叠的背景常识 (x)html文档中的元素默认处于普通流(normal flow)中,也就是说其顺序由元素在文档中的先后位置决定,此时一般不会产生重叠(但指定负边距可能产生重叠).当我们用cs ...

  2. ok6410 u-boot-2012.04.01移植六完善MLC NAND支持

    继ok6410 u-boot-2012.04.01移植四.五后,开发板基本已支持MLC NAND,支持DM9000.但是通过NAND命令更新u-boot到NAND,还存在问题,需要根据u-boot的n ...

  3. ok6410 u-boot-2012.04.01移植七完善u-boot移植(u-boot移植结束)

    继ok6410 u-boot-2012.04.01移植六后,开发板已支持MLC NAND.DM9000等.但还需要完善比如环境变量.mtdpart分区.裁剪.制作补丁等.下面的工作就是完善移植的u-b ...

  4. ok6410 u-boot-2012.04.01移植五支持DM9000

    继ok6410 u-boot-2012.04.01移植四后,开发板基本已支持MLC NAND,但还有一些细节地方修改,这节增加DM9000支持,通过网卡tftp程序到内存,接着通过NAND命令写到NA ...

  5. ok6410 u-boot-2012.04.01移植二修改源码支持单板

    继ok6410 u-boot-2012.04.01移植一后修改代码,对ok6410单板初始化,主要包括时钟.串口.NAND.DDR等初始化.这些工作在以前的裸板程序都写了,直接拿来用.我觉得先写裸板程 ...

  6. 移植u-boot-2012.04.01到JZ2440

    开发环境:Ubuntu 12.04 开发板:JZ2440  256M NandFlash  64M SDRAM 交叉编译器:arm-linux-gcc-4.3.2 u-boot:u-boot-2012 ...

  7. uboot-2012.04.01移植编译前准备

    一:准备移植1.从下面的官网下载uboot-2012.04.012.建立sourceinsight工程 a.解压并在E:\colin weidongshan\transplant_u-boot-201 ...

  8. 黑马_13 Spring Boot:04.spring boot 配置文件

    13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 05.spring boot 整合其他 ...

  9. http://www.cnblogs.com/stephen-liu74/archive/2012/08/01/2561557.html

    http://www.cnblogs.com/stephen-liu74/archive/2012/08/01/2561557.html

随机推荐

  1. Bugtags,产品经理的瑞士军刀

    做为设计移动应用的产品经理,每天的主要工作就是在手机上不停的体验自己的产品,发现问题.优化体验.你是否经常工作在这样的尴尬场景: 发现界面问题,将问题界面截屏传到电脑,用图片标记工具将问题标记出来,然 ...

  2. 解决docker不能下载镜像

    试了很多办法.用ss,vpn,都不行. 修改 /etc/default/docker的方式貌似在 1.12不好使了.最后找到和这个办法 http://blog.csdn.net/gsying1474/ ...

  3. ruby 字符串学习2

    在一个ruby字符串中包含表但是或者变量.想使用不同的值替换表达式或者变量 1 类似java 或者python的printf-style方式 template = 'Oceania has alway ...

  4. Intellisense in Visual Studio for Microsoft Dynamics CRM 2016

    Intellisense in Visual Studio for Microsoft Dynamics CRM 2016 posted by dynamicsnick on may 18, 2016 ...

  5. nginx 反向代理(Reverse Proxy)与耗时记录

    反向代理服务器位于实际的服务器之前,他能够缓存服务器响应,加速访问,同时也启到了负载均衡服务器的效果.反向代理服务器解析客户端请求,根据负载均衡算法转发到不同的后台服务器上.用户和后台服务器之间不再有 ...

  6. 监控RAC中的临时表空间

    it is from metalink:Note:465840.1 1>Monitor the temp space allocation to make sure each instance ...

  7. jdk线程的同步问题

    一.银行取款引出的问题 模拟银行取钱的例子: public class ThreadDemo06 { public static void main(String[] args) { Bank ban ...

  8. JAVA中求解对象所占字节大小

    该类为cache4j缓存框架中的工具类方法,该方法实现了两个接口 接口1:计算对象在内存中所占字节数 接口2:复制对象,实现深度克隆效果,实现原理为先序列化对象,然后在反序列化对象:返回一个新的对象, ...

  9. Fiddler录制jmeter脚本--V4.4..0.1版本

      圣诞节到了,圣诞老人送平安,我们送技术,我们知道以前jmeter的脚本来源有三个,手动书写.badboy录制.自带的录制功能(jmeter3.0该功能还比较好),目前我们又多了一个fiddler生 ...

  10. 应用层(一)HTTP服务访问基本流程和HTTP报文详解

    HTTP属于TCP/IP模型中一个面向文本的应用层协议,所使用的服务器端口号的TCP中的80端口,通信双方在这个基础上进行通信. 每个服务器都有一个应用进程,时刻监听着80端口的用户访问请求.当有用户 ...