• 移植u-boot-1.1.6(原创)


    #u-boot:u-boot-1.1.6
    #server:ubuntu 12.04
    #gcc: arm-linux-gcc -4.3.2
    #


    一、建立单板
    1> /board/smdk2410 : cp /board/smdk2410 /board/smdk2440
    2> /board/smdk2440 : mv smdk2410.c smdk2440.c
    3> /board/smdk2440 : Makefile smdk2410.o smdk2440.o
    4> 顶层Makefile
    smdk2440_config : unconfig
    @$(MKCONFIG) $(@:_config=) arm arm920t smdk2440 NULL s3c24x0
    5> /include/configs: cp smdk2410.h smdk2440.h

    编译:
    make smdk2440_config
    make


    二、 支持sdram :
    board/smdk2440/lowlevel.S
    #define REFCNT 1113
    ==>
    #define REFCNT 0x4f4


    三、修改时钟
    1> /board/smdk2440/smdk2440.c
    目的:
    FCLK=400MHz
    FCLK:HCLK:PCLK =1:4:8
    UPLL=48MHz,即UCLK=48MHz
    修改:
    ..smdk2440/smdk2440.c

    #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
    #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
    #define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */

    int board_init (void)
    {
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

    clk_power->CLKDIVN = S3C2440_CLKDIV;

    __asm__( "mrc p15, 0, r1, c1, c0, 0 " /* read ctrl register */
    "orr r1, r1, #0xc0000000 " /* Asynchronous */
    "mcr p15, 0, r1, c1, c0, 0 " /* write ctrl register */
    :::"r1"
    );
    ...
    clk_power->LOCKTIME = 0xFFFFFFFF;
    clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
    delay (4000);
    clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
    delay (8000);
    gd->bd->bi_arch_number = MACH_TYPE_S3C2440;


    /* adress of boot parameters */
    gd->bd->bi_boot_params = 0x30000100;
    }

    2> 修改speed.c //cpu/arm920t/s3c24x0/
    编译出错:
    speed.c: In function `get_HCLK':
    speed.c:107: error: structure has no member named `CAMDIVN'
    speed.c: In function `get_PCLK':
    speed.c:142: error: structure has no member named `CAMDIVN'
    make[1]: *** [speed.o] 错误 1

    原因: 2440时钟设置比2410多一些寄存器
    解决:
    在include/s3c24x0.h里面添加`CAMDIVN'即可
    /**################################################################################################**/
    四、支持NOR
    include/configs/smdk2440.h
    修改为:
    /*-----------------------------------------------------------------------
    * FLASH and environment organization
    */

    //注释掉下面两个类型的Nor Flash设置(CONFIG_AMD_LV400,CONFIG_AMD_LV800),因为不是我们所使用的型号
    #if 0
    #define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
    #define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
    #endif

    //add by fanlin for smdk2440 MX29LV160B
    #define CONFIG_MX29LV160B 1

    #ifdef CONFIG_MX29LV160B
    #define CONFIG_MX29LV160B 1 //jz2440 Nor Flash
    #define PHYS_FLASH_SIZE 0x200000 //2M
    #define CFG_MAX_FLASH_SECT (35) //扇区数
    #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x80000) //0x80000为参数开始存放位置
    #endif

    添加id
    >vi include/flash.h

    第181行添加
    //add by fanlin
    #define MX29LV160B 0x22492249


    在board/smdk2440/flash.c修改:
    //add by fanlin
    #define MAIN_SECT_SIZE 0x8000 // 定义为32k,主要扇区的大小

    //#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
    //#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))

    屏蔽LV400/LV800后需要识别:flash.c
    #elif defined(CONFIG_AMD_LV800)
    (AMD_MANUFACT & FLASH_VENDMASK) |
    (AMD_ID_LV800B & FLASH_TYPEMASK);
    #elif defined(CONFIG_MX29LV160B) //add by fanlin
    (AMD_MANUFACT & FLASH_VENDMASK) |
    (MX29LV160B & FLASH_TYPEMASK);

    由于我们是把norflash连接到了s3c2440的bank0上,因此norflash中的地址相对于s3c2440来说基址为0x00000000,即CFG_FLASH_BASE = 0。
    而之所以又把norflash中的地址向左移一位(即乘以2),是因为我们是把s3c2440的ADDR1连接到了norflash的A0上的缘故。

    由数据手册可知EN29LV160AB第0扇区大小为8K,第1、2为4K,第3为16K,后面31扇区为32K。前面4个扇区加起来刚好是主要扇区的大小 = 32K, 所以修改87行下如下

    for (j = 0; j < flash_info[i].sector_count; j++) //主要修改几个数字
    {
    if (j <= 3)
    {
    /* 1st one is 8 KB */
    if (j == 0)
    {
    flash_info[i].start[j] = flashbase + 0;
    }

    /* 2nd and 3rd are both 4 KB */
    if ((j == 1) || (j == 2))
    {
    flash_info[i].start[j] = flashbase + 0x2000 + (j - 1) * 0x1000;
    }

    /* 4th 16 KB */
    if (j == 3)
    {
    flash_info[i].start[j] = flashbase + 0x4000;
    }
    }
    else
    {
    flash_info[i].start[j] = flashbase + (j - 3) * MAIN_SECT_SIZE;
    }
    }
    size += flash_info[i].size;

    修改flash_print_info,添加MX29LV160B相关信息如下:


    switch (info->flash_id & FLASH_VENDMASK) {
    case (AMD_MANUFACT & FLASH_VENDMASK):
    printf ("AMD: ");
    break;
    case (MX_MANUFACT & FLASH_VENDMASK): //add by fanlin
    printf ("MXIC: ");
    break;
    default:
    printf ("Unknown Vendor ");
    break;
    }

    switch (info->flash_id & FLASH_TYPEMASK) {
    case (AMD_ID_LV400B & FLASH_TYPEMASK):
    printf ("1x Amd29LV400BB (4Mbit) ");
    break;
    case (AMD_ID_LV800B & FLASH_TYPEMASK):
    printf ("1x Amd29LV800BB (8Mbit) ");
    break;
    case (MX29LV160B & FLASH_TYPEMASK): //add by fanlin
    printf ("1x MX29LV160B (16Mbit) ");
    break;
    default:
    printf ("Unknown Chip Type ");
    goto Done;
    break;
    }

    修改int flash_erase (flash_info_t * info, int s_first, int s_last)
    if ((info->flash_id & FLASH_VENDMASK) !=
    //(AMD_MANUFACT & FLASH_VENDMASK)) {
    (MX_MANUFACT & FLASH_VENDMASK)) {
    return ERR_UNKNOWN_FLASH_VENDOR;
    }
    至此,uboot关于Norflash已经移植好

    以上,只是识别了nor,但是并不能启动内核
    /*##############################################################################################*/
    以上怀疑,nor并没能被正确识别,因为修改#define MX29LV160B 0x22492249对打印信息没影响
    采用u-boot.2012.04.01移植方法:

    在drivers里面添加jedec_flash.c,修改Makefile

    1>在board/smdk2440/Makefile 里面去掉flash.o
    2>在include/configs/smdk2440.h里面添加

    #define CFG_FLASH_CFI 1
    #define CFG_FLASH_CFI_DRIVER 1


    在flash.h里面添加:
    ypedef struct {
    ulong size; /* total bank size in bytes */
    ushort sector_count; /* number of erase units */
    ulong flash_id; /* combined device & manufacturer code */
    ulong start[CFG_MAX_FLASH_SECT]; /* physical sector start addresses */
    uchar protect[CFG_MAX_FLASH_SECT]; /* sector protection status */
    #ifdef CFG_FLASH_CFI
    uchar portwidth; /* the width of the port */
    uchar chipwidth; /* the width of the chip */
    ushort buffer_size; /* # of bytes in write buffer */
    ulong erase_blk_tout; /* maximum block erase timeout */
    ulong write_tout; /* maximum write timeout */
    ulong buffer_write_tout; /* maximum buffer write timeout */
    ushort vendor; /* the primary vendor id */
    ushort cmd_reset; /* vendor specific reset command */
    ushort interface; /* used for x8/x16 adjustments */
    ushort legacy_unlock; /* support Intel legacy (un)locking */
    //add by fanlin
    uchar manufacturer_id; /* manufacturer id */
    ushort device_id; /* device id */
    ushort device_id2; /* extended device id */
    ushort ext_addr; /* extended query table address */
    ushort cfi_version; /* cfi version */
    ushort cfi_offset; /* offset for cfi query */
    ulong addr_unlock1; /* unlock address 1 for AMD flash roms */
    ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
    //end of fanlin
    #endif

    怎么样可以让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,这是需要借助数据手册仿写一个

    jedec_flash_match在jedec_flash.c里面,我把这个文件从u-boot-2012.04.01里面直接拿过来放在drivers/下
    并修改Makefile


    以上可以在nor里面启动内核,但是弄好nand后,在nand启动会出现如下内容:
    DRAM: 64 MB
    ## Unknown FLASH on Bank 0 - Size = 0x00000000 = 0 MB
    Flash: 0 kB
    NAND: 256 MiB
    *** Warning - bad CRC or NAND, using default environment

    表示nor没有被识别:
    查看“Flash: ”的位置发现:
    DRAM: 打印信息在init_sequence --> display_dram_config
    Flash: 打印信息在start_armboot --> display_flash_config
    NAND: 打印信息在start_armboot -->puts ("NAND: ") -->nand_init

    对于flash来说,其实现这里不是flash.c里面,因为我们使用的芯片不是lv400或者LV800
    flash_init在cfi_flash.c里面

    高版本uboot里面使用如下来识别cfi协议下的nor:
    if (!flash_detect_legacy (BANK_BASE(i), i))
    jedec_flash_match 匹配
    flash_get_size (BANK_BASE(i), i);


    因为:启动内核依赖#define CONFIG_BOOTCOMMAND "nboot 0x32000000 0 0 ; bootm 0x32000000"
    这表明需要支持nand命令

    /**################################################################################################**/
    支持NAND 启动
    首先增加nand命令 include/configs/smdk2440.h
    #define CONFIG_COMMANDS
    ((CONFIG_CMD_DFL |
    ...
    CFG_CMD_NAND |

    直接编译
    error:
    nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)
    nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)
    nand.c:35: error: storage size of `nand_info' isn't known
    nand.c:37: error: storage size of `nand_chip' isn't known
    nand.c:38: error: storage size of `base_address' isn't known
    解决:
    在配置文件smdk2440.h里面添加三个宏
    #define CFG_NAND_BASE 0
    #define CFG_MAX_NAND_DEVICE 1
    #define NAND_MAX_CHIPS 1
    只剩一个error:
    ..nand/nand.c:50: undefined reference to `board_nand_init'
    解决:
    在cpu/arm920t/s3c24x0/下建立新文件nand_flash.c实现board_nand_init函数

    但是先定义结构体 在include/s3c24x0.h添加 S3C2440_NAND
    /* for 2440 nand flash */
    typedef struct{
    S3C24X0_REG32 NFCONF;
    S3C24X0_REG32 NFCONT;
    S3C24X0_REG32 NFCMD;
    S3C24X0_REG32 NFADDR;
    S3C24X0_REG32 NFDATA;
    S3C24X0_REG32 NFMECCD0;
    S3C24X0_REG32 NFMECCD1;
    S3C24X0_REG32 NFSECCD;
    S3C24X0_REG32 NFSTAT;
    S3C24X0_REG32 NFESTAT0;
    S3C24X0_REG32 NFESTAT1;
    S3C24X0_REG32 NFMECC0;
    S3C24X0_REG32 NFMECC1;
    S3C24X0_REG32 NFSECC;
    S3C24X0_REG32 NFSBLK;
    S3C24X0_REG32 NFEBLK;

    }S3C2440_NAND;

    nand_flash.c内容如下:
    /####################################################################################/start of nand_flash.c
    /*
    * Nand flash interface of s3c2410/s3c2440, by fanlin
    * Changed from drivers/mtd/nand/s3c2410.c of kernel 2.6.13
    */

    #include <common.h>

    #if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
    #include <s3c2410.h>
    #include <nand.h>

    DECLARE_GLOBAL_DATA_PTR;

    #define S3C2410_NFSTAT_READY (1<<0)
    #define S3C2410_NFCONF_nFCE (1<<11)

    #define S3C2440_NFSTAT_READY (1<<0)
    #define S3C2440_NFCONT_nFCE (1<<1)


    /* select chip, for s3c2410 */
    static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
    {
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    if (chip == -1) {
    s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
    } else {
    s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
    }
    }

    /* command and control functions, for s3c2410
    *
    * Note, these all use tglx's method of changing the IO_ADDR_W field
    * to make the code simpler, and use the nand layer's code to issue the
    * command and address sequences via the proper IO ports.
    *
    */
    static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
    {
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    struct nand_chip *chip = mtd->priv;

    switch (cmd) {
    case NAND_CTL_SETNCE:
    case NAND_CTL_CLRNCE:
    printf("%s: called for NCE ", __FUNCTION__);
    break;

    case NAND_CTL_SETCLE:
    chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
    break;

    case NAND_CTL_SETALE:
    chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
    break;

    /* NAND_CTL_CLRCLE: */
    /* NAND_CTL_CLRALE: */
    default:
    chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
    break;
    }
    }

    /* s3c2410_nand_devready()
    *
    * returns 0 if the nand is busy, 1 if it is ready
    */
    static int s3c2410_nand_devready(struct mtd_info *mtd)
    {
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
    }


    /* select chip, for s3c2440 */
    static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
    {
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    if (chip == -1) {
    s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
    } else {
    s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
    }
    }

    /* command and control functions */
    static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
    {
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
    struct nand_chip *chip = mtd->priv;

    switch (cmd) {
    case NAND_CTL_SETNCE:
    case NAND_CTL_CLRNCE:
    printf("%s: called for NCE ", __FUNCTION__);
    break;

    case NAND_CTL_SETCLE:
    chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
    break;

    case NAND_CTL_SETALE:
    chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
    break;

    /* NAND_CTL_CLRCLE: */
    /* NAND_CTL_CLRALE: */
    default:
    chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
    break;
    }
    }

    /* s3c2440_nand_devready()
    *
    * returns 0 if the nand is busy, 1 if it is ready
    */
    static int s3c2440_nand_devready(struct mtd_info *mtd)
    {
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
    }

    /*
    * Nand flash hardware initialization:
    * Set the timing, enable NAND flash controller
    */
    static void s3c24x0_nand_inithw(void)
    {
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    #define TACLS 0
    #define TWRPH0 4
    #define TWRPH1 2


    /* Set flash memory timing */
    s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
    /* Initialize ECC, enable chip select, NAND flash controller enable */
    s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);

    }

    /*
    * Called by drivers/nand/nand.c, initialize the interface of nand flash
    */
    void board_nand_init(struct nand_chip *chip)
    {
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    s3c24x0_nand_inithw();


    chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;
    chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
    chip->hwcontrol = s3c2440_nand_hwcontrol;
    chip->dev_ready = s3c2440_nand_devready;
    chip->select_chip = s3c2440_nand_select_chip;
    chip->options = 0;

    chip->eccmode = NAND_ECC_SOFT;
    }

    #endif

    /####################################################################################/end of nand_flash.c

    仿照include/s3c2410.h里面的S3C2410_GetBase_NAND函数定义S3C2440_GetBase_NAND函数
    /* FOR 2440 */
    static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
    {
    return (S3C2440_NAND * const)S3C2410_NAND_BASE;
    }

    还得添加默认环境变量才可以nor flash启动内核

    在smdk2440.h里面添加环境变量
    #define CONFIG_SETUP_MEMORY_TAGS 1
    #define CONFIG_CMDLINE_TAG 1

    //#define CONFIG_BOOTCOMMAND "nboot 0x30000000 0 0 ; bootm 0x30000000"
    #define CONFIG_BOOTCOMMAND "nand read.jffs2 0x30007FC0 0x60000 0x200000; bootm 0x30007FC0"

    这样就可以启动内核了。
    /**################################################################################################**/

    支持mtdpart分区
    搜索可知,mtdpart在cmd_jffs2.c里面定义

    1.在smdk2440.h里面添加命令CFG_CMD_JFFS2

    #define CONFIG_JFFS2_CMDLINE 1
    #define CONFIG_JFFS2_NAND 1

    #define MTDIDS_DEFAULT "nand0=nandflash0"
    #define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader),"
    "128k(params),"
    "2m(kernel),"
    "-(root)"

    以上,不能发现mtdpart分区
    cmd_jffs2里面do_jffs2_mtdparts函数开始修改为:
    setenv("mtdids", (char *)mtdids_default);
    setenv("mtdparts", (char *)mtdparts_default);
    setenv("partition", NULL);


    mtdparts_init();


    if (argc == 2) {
    if (strcmp(argv[1], "default") == 0) {
    //setenv("mtdids", (char *)mtdids_default);
    //setenv("mtdparts", (char *)mtdparts_default);
    //setenv("partition", NULL);


    //mtdparts_init();
    ...
    100ask处理办法如下:
    在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


    /**################################################################################################**/

    输入print命令打印如下:
    bootdelay=3
    baudrate=115200
    ipaddr=10.0.0.110
    serverip=10.0.0.1
    netmask=255.255.255.0
    stdin=serial
    stdout=serial
    stderr=serial

    配置网络ping主机
    CS8900 Ethernet chip not found?!

    支持dm9000


    在driver下,有网卡驱动DM9000x.c和 DM9000x.h
    DM9000接在BANK4,位宽16

    在include/configs/smdk2440.h中设置网卡基地址:
    在56行处,将CS8900的定义改成:

    #if 1
    #if 0
    #define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
    #define CS8900_BASE 0x19000300
    #define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
    #endif

    #if !defined(CONFIG_DRIVER_CS8900)
    #define CONFIG_DRIVER_DM9000 1
    #define CONFIG_DM9000_USE_16BIT 1
    #define CONFIG_DM9000_BASE 0x20000000
    #define DM9000_IO 0x20000000
    #define DM9000_DATA 0x20000004
    #endif
    #endif

    编译可生成支持网卡的uboot
    如果显示:
    # ping 10.140.1.250
    MAC: 08:08:08:08:008:08
    could not establish link

    将100ask的dm9000x.c替换当前的文件,说明dm9000x.c里面有问题,日后再研究

    烧录后显示:
    SMDK2440 # ping 192.168.1.17
    ERROR: resetting DM9000 -> not responding
    dm9000 i/o: 0x20000000, id: 0x90000a46
    DM9000: running in 16 bit mode
    MAC: 00:0c:29:45:c4:c5
    could not establish link
    host 192.168.1.17 is alive

    表示ping通了。

    /**################################################################################################**/
    设置环境变量的存储地址:


    原来的环境变量的配置:
    #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

    分区:
    device nand0 <nandflash0>, # parts = 4
    #: name size offset mask_flags
    0: bootloader 0x00040000 0x00000000 0
    1: params 0x00020000 0x00040000 0
    2: kernel 0x00200000 0x00060000 0
    3: root 0x0fda0000 0x00260000 0


    综上所知设置为:
    //#define CFG_ENV_IS_IN_FLASH 1
    #define CFG_ENV_IS_IN_NAND 1
    #define CFG_ENV_OFFSET 0x40000
    #define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */


    bootcmd=nand read.jffs2 30000000 kernel; bootm 30000000

    /***************************************分界线********************************************/
    支持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

    烧写ok

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


    出现错误:
    nand_write_ecc: Attempt to write not page aligned data
    0 bytes written: ERROR


    措施:

    在cmd_nand.c里面U_BOOT_CMD(nand, 5, 1, do_nand,
    添加
    "nand read.yaffs addr off size - read the `size' byte yaffs image starting "
    " at offset `off' to memory address `addr' "
    "nand write.yaffs addr off size - write the `size' byte yaffs image starting "
    " at offset `off' from memory address `addr' "

    do_nand函数里面:
    else if ( s != NULL && !strcmp(s, ".yaffs")){
    if (read) {
    /* read */
    nand_read_options_t opts;
    memset(&opts, 0, sizeof(opts));
    opts.buffer = (u_char*) addr;
    opts.length = size;
    opts.offset = off;
    opts.readoob = 1;
    opts.quiet = quiet;
    ret = nand_read_opts(nand, &opts);
    } else {
    /* write */
    nand_write_options_t opts;
    memset(&opts, 0, sizeof(opts));
    opts.buffer = (u_char*) addr;
    opts.length = size;
    opts.offset = off;
    /* opts.forceyaffs = 1; */ 注意这里
    opts.noecc = 1;
    opts.writeoob = 1;
    opts.blockalign = 1;
    opts.quiet = quiet;
    opts.skipfirstblk = 1; 新添加的
    ret = nand_write_opts(nand, &opts);
    }
    在nand.h里面加上opts.skipfirstblk以及其实现

    struct nand_write_options {
    u_char *buffer; /* memory block containing image to write */
    ulong length; /* number of bytes to write */
    ulong offset; /* start address in NAND */
    int quiet; /* don't display progress messages */
    int autoplace; /* if true use auto oob layout */
    int forcejffs2; /* force jffs2 oob layout */
    int forceyaffs; /* force yaffs oob layout */
    int noecc; /* write without ecc */
    int writeoob; /* image contains oob data */
    int pad; /* pad to page size */
    int blockalign; /* 1|2|4 set multiple of eraseblocks
    * to align to */
    int skipfirstblk; //这两项添加的
    int nocheckbadblk;

    };

    修改nand_write_opts函数,对int skipfirstblk的支持,文件在nand_util.c的nand_write_opts

    int skipfirstblk = opts->skipfirstblk;

    /* skip the first good block when wirte yaffs image, by www.100ask.net */
    if (skipfirstblk) {
    mtdoffset += erasesize_blockalign;
    skipfirstblk = 0;
    continue;
    }

    上面由于不用ecc,会出现很多警告信息如:
    Writing data without ECC to NAND-FLASH is not recommended
    可以在nand_base.c里面的nand_write_page函数里面屏蔽掉:
    case NAND_ECC_NONE:
    //printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended ");
    this->write_buf(mtd, this->data_poi, mtd->oobblock);

    补丁制作过程:
    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.xx u-boot-2012.xx_ok > u-boot-2012.xx.patch

    补丁制作ok。

  • 相关阅读:
    CRM 客户线索 与 销售人员
    CRM X
    MySQL为Null导致的5大坑
    搞懂 macOS 上的主机名/hostname/ComputerName
    Node服务中如何写日志?
    Linux下 iptables 超详细教程和使用示例
    精读《Prisma 的使用》
    Redis夺命20问
    redis HyperLogLog的使用
    聊聊redis分布式锁的8大坑
  • 原文地址:https://www.cnblogs.com/hulig7/p/4755825.html
Copyright © 2020-2023  润新知