• 移植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))


            
           

  • 相关阅读:
    ORM框架-SQLAchemy使用
    python与MySQL
    python 与rabbitmq
    阻止微信浏览器/QQ浏览器长按弹框“在浏览器打开”
    解决ios不支持按钮:active伪类的方法
    HTTP-FLV直播初探
    对比requirejs更好的理解seajs
    ‘true’==true返回false详解
    支付宝wap支付调起客户端
    JavaScript中基本数据类型和引用数据类型的区别
  • 原文地址:https://www.cnblogs.com/hulig7/p/4678582.html
Copyright © 2020-2023  润新知