总览
本文使用 linux-2.6.22.6 内核, 使用jz2440开发板.
源码
由 nand flash 系统框架 分析可知, Linux内核系统以及完成了Nand Flash设备的绝大部分的核心工作.
因此Nand Flash驱动真正要做的工作主要就是:
- 分配并初始化
nand_chip
结构体
- 初始化硬件
- 调用
nand_scan
- 调用
add_mtd_partitions
可以参考内核文件的相关源码, 学着写.
drivers\mtd\nand\at91_nand.c
drivers\mtd\nand\s3c2410.c
流程如下图:
s3c_nand.c
#include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/clk.h>
#include <asm/io.h> #include <asm/arch/regs-nand.h> #include <asm/arch/nand.h>
MODULE_LICENSE("GPL"); MODULE_AUTHOR("DRAAPHO");
struct s3c_nand_regs { unsigned long nfconf ; unsigned long nfcont ; unsigned long nfcmd ; unsigned long nfaddr ; unsigned long nfdata ; unsigned long nfeccd0 ; unsigned long nfeccd1 ; unsigned long nfeccd ; unsigned long nfstat ; unsigned long nfestat0; unsigned long nfestat1; unsigned long nfmecc0 ; unsigned long nfmecc1 ; unsigned long nfsecc ; unsigned long nfsblk ; unsigned long nfeblk ; };
static struct nand_chip *s3c_nand; static struct mtd_info *s3c_mtd; static struct s3c_nand_regs *s3c_nand_regs;
static struct mtd_partition s3c_nand_parts[] = { [0] = { .name = "bootloader", .size = 0x00040000, .offset = 0, }, [1] = { .name = "params", .offset = MTDPART_OFS_APPEND, .size = 0x00020000, }, [2] = { .name = "kernel", .offset = MTDPART_OFS_APPEND, .size = 0x00200000, }, [3] = { .name = "root", .offset = MTDPART_OFS_APPEND, .size = MTDPART_SIZ_FULL, } };
static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr) { if (chipnr == -1) { s3c_nand_regs->nfcont |= (1<<1); } else { s3c_nand_regs->nfcont &= ~(1<<1); } }
static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) { if (ctrl & NAND_CLE) { s3c_nand_regs->nfcmd = dat; } else { s3c_nand_regs->nfaddr = dat; } }
static int s3c2440_dev_ready(struct mtd_info *mtd) { return (s3c_nand_regs->nfstat & (1<<0)); }
static int s3c_nand_init(void) { struct clk *clk;
s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
s3c_nand->select_chip = s3c2440_select_chip; s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl; s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata; s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata; s3c_nand->dev_ready = s3c2440_dev_ready; s3c_nand->ecc.mode = NAND_ECC_SOFT;
clk = clk_get(NULL, "nand"); clk_enable(clk);
#define TACLS 0 #define TWRPH0 1 #define TWRPH1 0 s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
s3c_nand_regs->nfcont = (1<<1) | (1<<0);
s3c_mtd->owner = THIS_MODULE; s3c_mtd->priv = s3c_nand; nand_scan(s3c_mtd, 1);
return 0; }
static void s3c_nand_exit(void) { del_mtd_partitions(s3c_mtd); iounmap(s3c_nand_regs); kfree(s3c_mtd); kfree(s3c_nand); }
module_init(s3c_nand_init); module_exit(s3c_nand_exit);
|
Makefile
obj-m := s3c_nand.o KERN_SRC := /home/draapho/share/jz2440/kernel/linux-2.6.22.6/ PWD := $(shell pwd)
modules: make -C $(KERN_SRC) M=$(PWD) modules
clean: make -C $(KERN_SRC) M=$(PWD) clean
|
测试1
源码没有调用 add_mtd_partitions
时, 简单测试一下NAND Flash是否正常工作了.
$ make modules
$ insmod s3c_nand.ko NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit) Scanning device for bad blocks ......
|
测试2
源码调用 add_mtd_partitions
时, 测试过程比较复杂.
- 卸载内核自带的NAND Flash驱动
- 导致无法从本地Flash启动, 必须设置为从nfs启动
- 从nfs启动后, 加载 s3c_nand.ko 驱动.
- 使用工具
mtd-utils
格式化 NAND Flash
- 格式化后, 就能挂载测试了.
- 恢复原来的开发环境.
这个实验我没有实际去做, 设置和恢复都太麻烦. 而且正常的开发过程是不会这样去操作的.
下面给出实验步骤:
$ make clean $ make menuconfig
$ make uImage
$ sudo dnw ./arch/arm/boot/uImage
2. 导致无法从本地Flash启动, 必须设置为从nfs启动.
printenv
set bootargs noinitrd root=/dev/nfs nfsroot=10.0.0.98:/fs ip=10.0.0.111:10.0.0.98:10.0.0.138:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
save reset
3. 从nfs启动后, 加载 s3c_nand.ko 驱动.
$ make modules
$ insmod s3c_nand.ko NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
4. 使用工具 mtd-utils 格式化 NAND Flash
$ tar xjf mtd-utils-05.07.23.tar.bz2 $ cd mtd-utils-05.07.23/util $ vim Makefile CROSS=arm-linux- $ make
$ cp flash_erase flash_eraseall /home/draapho/share/jz2440/nfs/fs_mini_mdev/bin
5. 格式化后, 就能挂载测试了.
$ ls -l /dev/mtd*
$ flash_eraseall /dev/mtd3 $ mount -t yaffs /dev/mtdblock3 /tmp $ ls /tmp
6. 恢复原来的开发环境
|
参考资料
Linux操作系统下 NAND FLASH驱动程序框架
原创于 DRA&PHO