四,移植uboot-支持NOR,NAND 操作

本小妞迷上赌 提交于 2021-01-12 08:30:28

文档时间:2018-08-11

交叉编译器:arm-linux-gcc-4.3.2

Ubuntu版本:16.04

uboot版本:2013.10

 

1,修改代码支持 nor flash 操作

前面章节已经实现NOR,NAND 启动,但是还不支持nor,nand flash 操作,如下图打印信息所示:

Flash: ***  failed ***,搜索发现,此段错误信息在第二阶段 board_init_r 函数中,此函数位于 arch/arm/lib/board.c 文件中,代码如下所示:

#if !defined(CONFIG_SYS_NO_FLASH)
    puts("Flash: ");

    flash_size = flash_init();
    if (flash_size > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
        print_size(flash_size, "");
        /*
         * Compute and print flash CRC if flashchecksum is set to 'y'
         *
         * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
         */
        if (getenv_yesno("flashchecksum") == 1) {
            printf("  CRC: %08X", crc32(0,
                (const unsigned char *) CONFIG_SYS_FLASH_BASE,
                flash_size));
        }
        putc('\n');
# else    /* !CONFIG_SYS_FLASH_CHECKSUM */
        print_size(flash_size, "\n");
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
    } else {
        puts(failed);
        hang();
    }
#endif

从上面代码可以看出,如果nor flash 没有初始化成功,会执行红色部分代码,打印错误信息,陷入死循环,现更改代码,让其继续跑下去,代码更改如下(红色部分为修改代码):

# endif /* CONFIG_SYS_FLASH_CHECKSUM */
    } else {
        //puts(failed);
        //hang();
        puts("0 KB \n\r");
    }

 1)在 jz2440.h 中添加 DEBUG 的定义,使串口打印更多信息

#define DEBUG

然后,编译,烧写,串口打印信息如下图所示:

从图中可以看出已经读出厂家ID,设备ID了,但是不匹配,搜索 JEDEC PROBE 关键字,位于:

打开 drivers/mtd/cfi_flash.c 文件,定位到1798行,发现该字段位于 flash_detect_legacy 函数中,flash_detect_legacy 函数的调用关系如下:

board_init_r -> flash_init -> flash_detect_legacy,分析如下代码:

 该函数会进入到 jedec_flash_match(位于drivers/mtd/jedec_flash.c文件中) 函数,打开该文件,定位到jedec_flash_match 函数:

该函数里会去匹配 jedec_table ,定位到 jedec_table 定义处,发现没有与我们所用nor flash 相匹配的定义,参照所用 nor flash(MT29LV160DB)手册,增加如下代码(红色部分为增加代码):

static const struct amd_flash_info jedec_table[] = {
     /*MX29LV160DB*/
    {
        .mfr_id        = (u16)MX_MANUFACT,
        .dev_id        = AM29LV160DB,        //0x2249
        .name        = "MX29LV160DB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* 数组[1]表示是16位nor,解锁地址为:0x555,0x2AA */
        },
        .DevSize    = SIZE_2MiB,
        .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),
        }
    },

 

 注释掉 jz2440.h 中定义的 DEBUG 宏,然后编译,烧写到 nor flash,出现如下图所示错误:

搜索这段字符串,发现该段字符串位于 drivers/mtd/jedec_flash.c 中,打开 jedec_flash.c 文件,定位到这里:

显然是宏 CONFIG_SYS_MAX_FLASH_SECT 小于我们的扇区数量,才会打印这个错误,修改 CONFIG_SYS_MAX_FLASH_SECT (位于 include/configs/jz2440.h 中):

#define CONFIG_SYS_MAX_FLASH_SECT    (128)

重新编译烧写,打印如下信息:

输入 flinfo 命令,查看 flash 信息,如下图所示:

通过串口终端输入以下命令,来检查 nor flash 的读写是否满足我们的要求:

protect off all 
erase 10000 +7ffff              
cp.b 30000000 10000 80000             //烧写在另一个位置
cmp.b 30000000 10000 80000              //比较,是否读写正确

如果正确,则会打印如下信息:

 

2,修改代码,支持 nand flash 操作 

在修改代码之前先把串口终端名称 SMDK2410 改为 JZ2440,在 include/configs/jz2440.h 中修改,修改代码如下:

#define CONFIG_SYS_PROMPT    "JZ2440 # "

 在之前的章节中,我们把支持 nand 的宏 CONFIG_CMD_NAND 给屏蔽了,现在取消屏蔽(在 jz2440.h 中),然后添加对2440 nand 宏的支持,修改代码如下:

#ifdef CONFIG_CMD_NAND
//#define CONFIG_NAND_S3C2410
//#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC

 2410对于nand flash 的支持位于 drivers/mtd/nand/s3c2410_nand.c 中,仿照此文件,编写对2440 nand flash 的支持

在 Ubuntu 下,输入命令 cp drivers/mtd/nand/s3c2410_nand.c drivers/mtd/nand/s3c2440_nand.c 进行拷贝,然后修改Makefile,如下所示:

COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

 分析 nand 流程:board_init_r -> nand_init -> nand_init_chip -> board_nand_init 和 nand_scan

 1),进入 board_init_r 函数(arch/arm/lib/board.c里)

2),进入 nand_init 函数(drivers/mtd/nand/nand.c里)

3),进入 nand_init_chip 函数(drivers/mtd/nand/nand.c里)

 

调用 board_nand_init 和 nand_scan 函数

修改 drivers/mtd/nand/s3c2440_nand.c 支持我们所用的nand flash 芯片

首先将所有带有 2410 的变量 替换为 2440

然后参考以前裸机 nand 驱动程序或者S3C2440和所用nand 芯片手册修改 nand_board_init 函数,修改代码如下:

cfg = S3C2440_NFCONF_EN;
    cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
    writel(cfg, &nand_reg->nfconf);
    nand_reg->nfcont=(1<<1)|(1<<0); // bit1:关闭片选(),       bit0:开启nand flash 控制器

    /* initialize nand_chip data structure */
    nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
    nand->IO_ADDR_W = (void *)&nand_reg->nfdata;

    nand->select_chip=s3c2440_select_chip;

 编写 s3c2440_select_chip 函数,代码如下(这里可以参考别的单板的例程):

static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
    struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();

    if(chipnr==-1)          //CE Disable
   {
        nand_reg->nfcont|=(0x01<<1);               //bit1置1
   }
    else                         //CE Enable
   {
           nand_reg->nfcont&=~(0x01<<1);        //bit1置0 
   }           

}

修改  s3c2440_hwcontrol 函数,修改代码如下,(红色为修改部分):

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;
    struct s3c2440_nand *nand = s3c2440_get_base_nand();


    if (ctrl & NAND_CLE)                 // 传输的是命令
        nand->nfcmd=cmd;  
    else                                // 传输的是地址
        nand->nfaddr=cmd;  
}

代码修改完毕,编译,烧写,观察现象:

nand flash已经识别出来,接下来测试 nand flash 读写是否正确,输入以下命令:

nand erase 100000 1000                      //擦除
mw.b 30000000 0x55 1000
nand write 30000000 100000 1000        //将0x55写入nand
nand dump 100000 1000        //打印

 如下图所示,读写都没问题

 

到此为止,uboot 代码已经能够支持 jz2440 nor / nand flash 操作了,下一张移植 DM9000 网卡支持

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!