文档时间: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 网卡支持
来源:oschina
链接:https://my.oschina.net/u/4394044/blog/3872642