0 开发环境
宿主机:Ubuntu14.04
开发板:MIni2440
U-Boot:u-boot.1.1.6
1 准备工作
先根据《U-Boot移植——添加新开发板》添加对MIini2440的支持,然后再继续本文的工作。本文的工作主要参考参考资料[5]p276-283
2 include/configs/mini2440.h
(1)CFG_CMD_NAND
打开include/configs/mini2440.h,取消CFG_CMD_NAND的注释:
(2)CFG_NAND_BASE / CFG_MAX_NAND_DEVICE / NAND_MAX_CHIPS
添加上述CFG_CMD_NAND之后重新编译u-boot-1.1.6,出现以下错误:
在include/configs/mini2440.h的最后添加以下宏定义:
#define CFG_NAND_BASE 0 /* 无实际意义: 基地址, 在board_nand_init中重新指定 */
#define CFG_MAX_NAND_DEVICE 1 /* NAND Flash"设备"的数目为1 */
#define NAND_MAX_CHIPS 1 /* 每个NAND Flash "设备"由1个NAND Flash"芯片"组成 */
3 board_nand_init()
经过上述修改,再次编译提示:
由上图可见,缺乏board_nand_init()的实现。下面描述如何一步一步实现board_nand_init()函数。
(1)include/s3c24x0.h
打开include/s3c24x0.h,仿照S3C2410_NAND的定义添加S3C2440_NAND的定义:
/* NAND FLASH (see S3C2440 manual chapter 6) */
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;
} /*__attribute__((__packed__))*/ S3C2440_NAND;
上述结构中的成员都是S3C2440的Nand Flash寄存器,详见S3C2440手册p6-12。
(2)include/s3c2410.h
打开include/s3c2410.h,仿照S3C2410_GetBase_NAND()定义S3C2440_GetBase_Nand():
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
return (S3C2440_NAND * const)S3C2410_NAND_BASE;// 注:这里是S3C2410_NAND_BASE,不是S3C2440_NAND_BASE
}
(3)cpu/arm920t/s3c24x0/nand_flash.c
在cpu/arm920t/s3c24x0中创建一个源文件nand_flash.c,内容如下:
/*
* s3c2440的Nand Flash控制器接口
* 修改自Linux内核2.6.13文件drivers/mtd/nand/s3c2410.c
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <nand.h>
#include <s3c2410.h>
DECLARE_GLOBAL_DATA_PTR;
#define S3C2440_NFSTAT_READY (1<<0)
#define S3C2440_NFCONT_nFCE (1<<1)
/* NAND Flash的片选函数 */
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; /* 使能片选信号 */
}
}
/* 命令和控制函数 */
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\n", __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 Flash状态
* 返回值: 0表示忙, 1表示就绪
*/
static int s3c2440_nand_devready(struct mtd_info *mtd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}
/* Nand Flash硬件初始化 */
static void s3c24x0_nand_inithw(void)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
/* 设置时序 */
s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* 初始化ECC, 使能NAND Flash 控制器, 使能片选信号 */
s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
}
/*
* 被dirver/nand/nand.c调用, 初始化NAND Flash硬件, 初始化访问接口函数
*/
void board_nand_init(struct nand_chip *chip)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
s3c24x0_nand_inithw(); /*NAND Flash硬件初始化 */
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; /* 设置位宽等, 位宽为8 */
chip->eccmode = NAND_ECC_SOFT; /* ECC校验方式: 软件ECC */
}
#endif
(4)cpu/arm920t/s3c24x0/Makefile
在cpu/arm920t/s3c24x0/Makefile添加nand_flash.o:
4 编译&下载&运行
通过上述修改,可以重新编译u-boot-1.1.6,然后下载到Mini2440中运行:
可通过nand info命令进一步查看Nand Flash的信息:
也可以通过nand erase/write对Nand Flash进行擦除/写。
5 容易出错的地方
若根据参考资料[6]的提示可知这是s3c24x0_nand_inithw()有误所致的,例如将NFCONT误写为NFCONF时,就会出现上述错误。
参考资料
[1]u-boot移植之nand flash移植
[2]TQ2440的学习——UBOOT移植(NAND FLASH的支持)——初步分析
[3]UBOOT移植(NAND FLASH的支持)——初步移植 (一)
[4]UBOOT移植(NAND FLASH的支持)——初步移植 (二)
[5]韦东山. 嵌入式Linux应用开发完全手册. 人民邮电出版社,2012
[6]U-Boot出现No NAND device found!!!的解决办法