NAND FLASH驱动程序

发布者:JoyfulSpirit最新更新时间:2016-04-01 来源: eefocus关键字:NAND  FLASH  驱动程序 手机看文章 扫描二维码
随时随地手机看文章
// 参考 
 * drivers\mtd\nand\s3c2410.c
 * drivers\mtd\nand\at91_nand.c
 //
 
#include "linux/module.h"
#include "linux/types.h"
#include "linux/init.h"
#include "linux/kernel.h"
#include "linux/string.h"
#include "linux/ioport.h"
#include "linux/platform_device.h'
#include "linux/delay.h"
#include "linux/err.h"
#include "linux/slab.h"
#include "linux/clk.h"
 
#include "linux/mtd/mtd.h"
#include "linux/mtd/nand.h"
#include "linux/mtd/nand_ecc.h"
#include "linux/mtd/partitions.h"
 
#include "asm/io.h"
 
#include "asm/arch/regs-nand.h"
#include "asm/arch/nand.h"
 
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,                  //剩下的所有空间都是"root"分区
        }
};
 
 
static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
        if (chipnr == -1)
        {
               //取消选中: NFCONT[1]设为1 
                s3c_nand_regs->nfcont |= (1<<1);
        }
        else
        {        
               // 选中: NFCONT[1]设为0 
                s3c_nand_regs->nfcont &= ~(1<<1);
        }
}
 
static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
        if (ctrl & NAND_CLE)
        {
               // 发命令: NFCMMD=dat 
                s3c_nand_regs->nfcmd = dat;
        }
        else
        {
               // 发地址: NFADDR=dat 
                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;
       // 1. 分配一个nand_chip结构体 
        s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
 
        s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
       
       // 2. 设置nand_chip */
/ 设置nand_chip是给nand_scan函数使用的, 如果不知道怎么设置, 先看nand_scan怎么使用 
/ 它应该提供:选中,发命令,发地址,发数据,读数据,判断状态的功能
 //
        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;
       
        // 3. 硬件相关的设置: 根据NAND FLASH的手册设置时间参数 
// 使能NAND FLASH控制器的时钟 
        clk = clk_get(NULL, "nand");
        clk_enable(clk);              
       
        // HCLK=100MHz
* TACLS:  发出CLE/ALE之后多长时间才发出nWE信号, 从NAND手册可知CLE/ALE与nWE可以同时发出,所以TACLS=0
* TWRPH0: nWE的脉冲宽度, HCLK x ( TWRPH0 + 1 ), 从NAND手册可知它要>=12ns, 所以TWRPH0>=1
* TWRPH1: nWE变为高电平后多长时间CLE/ALE才能变为低电平, 从NAND手册可知它要>=5ns, 所以TWRPH1>=0
//
#define TACLS    0
#define TWRPH0   1
#define TWRPH1   0
        s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
 
       // NFCONT: 
* BIT1-设为1, 取消片选 
* BIT0-设为1, 使能NAND FLASH控制器
//
        s3c_nand_regs->nfcont = (1<<1) | (1<<0);
       // 4. 使用: nand_scan 
        s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
        s3c_mtd->owner = THIS_MODULE;
        s3c_mtd->priv  = s3c_nand;
        
        nand_scan(s3c_mtd, 1);  // 识别NAND FLASH, 构造mtd_info ,最大芯片个数1
       
       // 5. add_mtd_partitions 
        add_mtd_partitions(s3c_mtd, s3c_nand_parts, 4);  //分区数4
        //add_mtd_device(s3c_mtd);                                   //整个nand flash 作为一个分区使用
        return 0;
}
 
static void s3c_nand_exit(void)
{
        del_mtd_partitions(s3c_mtd);
        kfree(s3c_mtd);
        iounmap(s3c_nand_regs);
        kfree(s3c_nand);
}
 
module_init(s3c_nand_init);
module_exit(s3c_nand_exit);
 
MODULE_LICENSE("GPL");
=================================================================
NAND FLASH是一个存储芯片
那么: 这样的操作很合理"读地址A的数据,把数据B写到地址A"
 
问1. 原理图上NAND FLASH和S3C2440之间只有数据线,
     怎么传输地址?
答1.在DATA0~DATA7上既传输数据,又传输地址
     当ALE为高电平时传输的是地址,
 
问2. 从NAND FLASH芯片手册可知,要操作NAND FLASH需要先发出命令
     怎么传入命令?
答2.在DATA0~DATA7上既传输数据,又传输地址,也传输命令
     当ALE为高电平时传输的是地址,
     当CLE为高电平时传输的是命令
     当ALE和CLE都为低电平时传输的是数据
 
问3. 数据线既接到NAND FLASH,也接到NOR FLASH,还接到SDRAM、DM9000等等
     那么怎么避免干扰?
答3. 这些设备,要访问之必须"选中",
     没有选中的芯片不会工作,相当于没接一样
 
问4. 假设烧写NAND FLASH,把命令、地址、数据发给它之后,
     NAND FLASH肯定不可能瞬间完成烧写的,
     怎么判断烧写完成?
答4. 通过状态引脚RnB来判断:它为高电平表示就绪,它为低电平表示正忙
 
问5. 怎么操作NAND FLASH呢?
答5. 根据NAND FLASH的芯片手册,一般的过程是:
     发出命令
     发出地址
     发出数据/读数据
 
          NAND FLASH                      S3C2440
发命令    选中芯片                   
          CLE设为高电平                   NFCMMD=命令值     
          在DATA0~DATA7上输出命令值
          发出一个写脉冲
            
发地址    选中芯片                        NFADDR=地址值
          ALE设为高电平
          在DATA0~DATA7上输出地址值
          发出一个写脉冲
 
发数据    选中芯片                        NFDATA=数据值
          ALE,CLE设为低电平
          在DATA0~DATA7上输出数据值
          发出一个写脉冲
 
读数据    选中芯片                        val=NFDATA
          发出读脉冲
          读DATA0~DATA7的数据
 
用UBOOT来体验NAND FLASH的操作:
 
1. 读ID
                               S3C2440                 u-boot 
选中                           NFCONT的bit1设为0   md.l 0x4E000004 1; mw.l 0x4E000004  1
发出命令0x90                   NFCMMD=0x90         mw.b 0x4E000008 0x90 
发出地址0x00                   NFADDR=0x00         mw.b 0x4E00000C 0x00
读数据得到0xEC                 val=NFDATA          md.b 0x4E000010 1
读数据得到device code          val=NFDATA          md.b 0x4E000010 1
          0xda
退出读ID的状态                 NFCMMD=0xff         mw.b 0x4E000008 0xff
     
2. 读内容: 读0地址的数据
使用UBOOT命令:
nand dump 0
Page 00000000 dump:
        17 00 00 ea 14 f0 9f e5  14 f0 9f e5 14 f0 9f e5
 
                               S3C2440                 u-boot 
选中                           NFCONT的bit1设为0   md.l 0x4E000004 1; mw.l 0x4E000004  1
发出命令0x00                   NFCMMD=0x00         mw.b 0x4E000008 0x00 
发出地址0x00                   NFADDR=0x00         mw.b 0x4E00000C 0x00
发出地址0x00                   NFADDR=0x00         mw.b 0x4E00000C 0x00
发出地址0x00                   NFADDR=0x00         mw.b 0x4E00000C 0x00
发出地址0x00                   NFADDR=0x00         mw.b 0x4E00000C 0x00
发出地址0x00                   NFADDR=0x00         mw.b 0x4E00000C 0x00
发出命令0x30                   NFCMMD=0x30         mw.b 0x4E000008 0x30 
读数据得到0x17                 val=NFDATA          md.b 0x4E000010 1
读数据得到0x00                 val=NFDATA          md.b 0x4E000010 1
读数据得到0x00                 val=NFDATA          md.b 0x4E000010 1
读数据得到0xea                 val=NFDATA          md.b 0x4E000010 1
退出读状态                     NFCMMD=0xff         mw.b 0x4E000008 0xff
 
 
NAND FLASH驱动程序层次
 
看内核启动信息
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2440-nand s3c2440-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=3 30ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 256 at 0x02000000
Bad eraseblock 257 at 0x02020000
Bad eraseblock 319 at 0x027e0000
Bad eraseblock 606 at 0x04bc0000
Bad eraseblock 608 at 0x04c00000
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"
 
搜"S3C24XX NAND Driver"
S3c2410.c (drivers\mtd\nand)
 
s3c2410_nand_inithw
s3c2410_nand_init_chip
nand_scan  // drivers/mtd/nand/nand_base.c 根据nand_chip的底层操作函数识别NAND FLASH,构造mtd_info
    nand_scan_ident
        nand_set_defaults
if (!chip->select_chip)
chip->select_chip = nand_select_chip; // 默认值不适用
 
if (chip->cmdfunc == NULL)
chip->cmdfunc = nand_command;
chip->cmd_ctrl(mtd, command, ctrl);
if (!chip->read_byte)
chip->read_byte = nand_read_byte;
readb(chip->IO_ADDR_R);
if (chip->waitfunc == NULL)
chip->waitfunc = nand_wait;
chip->dev_ready
        
        
        nand_get_flash_type
            chip->select_chip(mtd, 0);
            chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
            *maf_id = chip->read_byte(mtd);
            dev_id = chip->read_byte(mtd);
    nand_scan_tail
    mtd->erase = nand_erase;
    mtd->read = nand_read;
    mtd->write = nand_write;
s3c2410_nand_add_partition
    add_mtd_partitions
        add_mtd_device
            list_for_each(this, &mtd_notifiers) { // 问. mtd_notifiers在哪设置
                                                  // 答. drivers/mtd/mtdchar.c,mtd_blkdev.c调用register_mtd_user
                struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
                not->add(mtd);
                // mtd_notify_add  和 blktrans_notify_add
                先看字符设备的mtd_notify_add
                        class_device_create
                        class_device_create
                再看块设备的blktrans_notify_add
                    list_for_each(this, &blktrans_majors) { // 问. blktrans_majors在哪设置
                                                            // 答. drivers\mtd\mdblock.c或mtdblock_ro.c   register_mtd_blktrans
                        struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);              
                        tr->add_mtd(tr, mtd);
                                mtdblock_add_mtd (drivers\mtd\mdblock.c)
                                    add_mtd_blktrans_dev
                                        alloc_disk
                                        gd->queue = tr->blkcore_priv->rq; // tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock);
                                        add_disk            
 
 
 
测试4th:
1. make menuconfig去掉内核自带的NAND FLASH驱动
-> Device Drivers
  -> Memory Technology Device (MTD) support
    -> NAND Device Support
   < >   NAND Flash support for S3C2410/S3C2440 SoC
2. make uImage
       使用新内核启动, 并且使用NFS作为根文件系统,因为之前根文件系统在nand flash上面,现在内核去除了nand flash的驱动,内核就无法访问根文件系统了。
 
3. insmod s3c_nand.ko
4. 格式化 (参考下面编译工具)
   flash_eraseall  /dev/mtd3                //擦除后本身就格式化成 yaffs文件系统,所以不用再格式化了
   
5. 挂接
   mount -t yaffs /dev/mtdblock3 /mnt
6. 在/mnt目录下建文件   
 
 
 
编译工具:
1. tar xjf mtd-utils-05.07.23.tar.bz2 
2. cd mtd-utils-05.07.23/util
修改Makefile:
#CROSS=arm-linux-
改为
CROSS=arm-linux-
3. make
4. cp flash_erase flash_eraseall /work/nfs_root/first_fs/bin/
         flash_erase :只擦除一个扇区
         flash_eraseall :整个分区都擦除掉

关键字:NAND  FLASH  驱动程序 引用地址:NAND FLASH驱动程序

上一篇:NOR FLASH驱动程序
下一篇:USB设备驱动程序

推荐阅读最新更新时间:2024-03-16 14:48

SK加码布局NAND市场,砸178亿建新厂
根据媒体报导,韩国存储器大厂SK海力士宣布将投资20万亿韩圆(约178亿美金)于今日启用的NAND芯片厂,比原来的预算15.5万亿韩圆还要多29%。 根据《韩联社》报导,这所新的M15新产线位于清州,SK海力士从2016年12月宣布兴建,并且于2017年4月动工,并已在今日完工启用,新厂将加强韩国存储器产业中的竞争力。SK计划持续扩大这条产线,不过详细内容将会视市场状况来决定。该厂将会在2019年第1季开始生产96层NAND Flash 快闪存储器,将会有月产20万片的程度,类似于位于首尔以南80公里的利川M14生产线。 SK海力士会长崔泰源宣示,身为国家的关键企业,SK海力士将会持续维持在市场的竞争力。韩国大统领文
[嵌入式]
SK加码布局<font color='red'>NAND</font>市场,砸178亿建新厂
Semico预测:NAND将渐入PC市场
  据市场调查公司Semico的Phoenix.Ariz说,NAND将在消费者不易察觉的情况下,逐渐进入PC市场。   Semico公司表示,随着微软的新操作系统Vista的推出和元件供应商Intel, Samsung等公司的推动,NAND将被设计为PC的硬盘驱动器和主存之间的高速缓存。   微软新操作系统Vista取代当前Windows系统的困难直到最近才被重视。Semico还指出,为了在媒体服务器市场竞争,微软意识到该操作系统的启动必须远远快于当前的任何Windows操作系统。其中的一个方法就是在硬盘上应用NAND缓存,或者在系统的别的地方应用,来加速硬盘。   这项技术衍生出了一些名字:Readydrive、混合硬盘(
[焦点新闻]
Linux2.6.32移植到MINI2440(2)添加Nand Flash驱动,修改分区
开发环境: 主机:fedora 14 虚拟机:vmware workstation 10 交叉编译工具:arm-linux-gcc 4.3.2 开发板:mini2440(2m nor ,64m sdram,256m nand) 一、添加头文件 在/arch/arm/mach-s3c2440/mach-mini2440.c中 vim mach_mini2440.c 添加进去如下头文件: #include linux/mtd/partitions.h #include linux/mtd/nand_ecc.h #include linux/mtd/mt
[单片机]
S3C2440-裸机篇-09 | 使用S3C2440操作Nor Flash
1. Nor Flash与Nand Flash Nor Nand 接口 引脚多,类似于RAM 引脚较少 容量 小(1-32MB) 大(128-512MB) 读操作 简单,和RAM相同 简单,和RAM相同 写操作 发出特定命令才能写入 发出特定命令才能写入 价格 贵 便宜 比较 无坏块 有坏块 XIP 可以 不可以 应用场合 存储关键性代码(比如uboot,kernel) 存储海量数据(允许错误) 2. JZ2440开发板上的Nor Flash JZ2440开发板上板载了一个Nor Flash,型号为MX29LV160DBTI-70G,连接在S3C2440内存控制器上的BANK0,原理图如下:
[单片机]
S3C2440-裸机篇-09 | 使用S3C2440操作Nor <font color='red'>Flash</font>
avr的flash和ram存放的数据问题
简介:本文介绍了AVR单片机内flash和RAM存放数据的区别以及使用等内容。 avr单片机是基于哈佛结构,它的程序存储器和数据存储器分开。 avr的Flash存储器空间存放的内容有: (1)text:程序代码区 (2)interrupt vectors:存放中断向量 (3)fun_lit:函数列表区。函数列表区包含了函数的入口地址。 (4)lit:整型数和浮点数常量区。存放的是程序中的常量数据。 (5)idata:全局变量和字符串的初始值存放在该区。 avr的RAM数据内存中存放的内容有: 1)data: 存放全局变量、静态变量和字符串。(注意:全局变量和字符串的初始值保存在Flash中的id
[单片机]
2012年Q1 NAND Flash厂营收排名,三星维持第一东芝紧追在后
    May 8, 2012---2012年第一季NAND Flash市场在全球经济复苏缓慢及中国农历年长假销售不如业者预期情况下,除了少数平板计算机及智能型手机客户的OEM需求较稳定外,多数的系统产品客户及记忆卡与随身碟通路市场客户需求,受淡季效应及消化过剩库存影响,呈现疲弱不振的状况。根据TrendForce旗下研究部门DRAMeXchange调查显示,市场在供过于求情况下,2012年第一季 NAND Flash品牌供货商的ASP较上季大幅下跌约16%,第一季整体NAND Flash品牌供货商的位元出货量较上季成长约16% ,故2012年第一季整体NAND Flash品牌供货商营收为47亿9千1百万美元,较上季减少约2.5%。
[手机便携]
第015课 NOR Flash操作原理及裸机程序分析
#第001节_Nor Flash原理及硬件操作 # Nor Flash的连接线有地址线,数据线,片选信号读写信号等,Nor Flash的接口属于内存类接口,Nor Flash可以向内存一样读,但是不能像内存一样写,需要做一些特殊的操作才能进行写操作,读只需像内存一样读很简单。 Nor Flash原理图如图: Flash介绍 常用的Flash类型有Nor Flash和NAND Flash两种。 Nor Flash由Intel公司在1988年发明,以替代当时在市场上占据主要地位的EPROM和E2PROM。NAND Flash由Toshiba公司在1989年发明。两者的主要差别如下表: Nor Flash支持XIP,即代码可以
[单片机]
第015课 NOR <font color='red'>Flash</font>操作原理及裸机程序分析
STM32 FLASH 掉电数据丢失处理策略以及备份机制
1、原因 由于FLASH的擦除和写入的特性,如果在擦除中掉电或者写入时掉电,有可能会出现失败的情况,下次再上电读取就会出错。 擦除的时候掉电,不能保证擦除完全,但是已经擦除的部分,肯定是0xff了。 写的时候掉电,已经写入的就是正确的,电平掉到最低极限工作电压附近时,写入的就无法保证了,地址无法保证,写入的值也无法保证。没有写到的,肯定还是 0xFF。   2、解决方式 2.1、硬件方式解决 — 掉电保护机制  必须硬件电路上有相应的掉电警告中断,而且必须有足够的时间供软件响应。   掉电保存和上电恢复,需要以下:  1) 快速检测掉电信号; 2) 要有足够的时间让你停下来保存现场; 3) 上电后可靠的复位;  这些的
[单片机]
STM32 <font color='red'>FLASH</font> 掉电数据丢失处理策略以及备份机制
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved