• 驱动09.nand flash


    1 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的芯片手册,一般的过程是:
         发出命令
         发出地址
         发出数据/读数据

    2 分析nand flash的启动过程

    搜"S3C24XX NAND Driver"
    S3c2410.c (driversmtd and)

    s3c2410_nand_inithw
    s3c2410_nand_init_chip
    nand_scan  // 根据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在哪设置
                                                                // 答. driversmtdmdblock.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 (driversmtdmdblock.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            

    3 nand flash驱动程序框架

    (1)分配一个nand_chip/mtd_info结构体

    (2)设置

    (3)硬件相关的操作

    (4)使用nand_scan/add_mtd_partitions

    4 写代码

    参考driversmtd ands3c2410.c

      1 /*参考driversmtd
    andat91_nand.c*/
      2 
      3 
      4 #include <linux/module.h>
      5 #include <linux/types.h>
      6 #include <linux/init.h>
      7 #include <linux/kernel.h>
      8 #include <linux/string.h>
      9 #include <linux/ioport.h>
     10 #include <linux/platform_device.h>
     11 #include <linux/delay.h>
     12 #include <linux/err.h>
     13 #include <linux/slab.h>
     14 #include <linux/clk.h>
     15 
     16 #include <linux/mtd/mtd.h>
     17 #include <linux/mtd/nand.h>
     18 #include <linux/mtd/nand_ecc.h>
     19 #include <linux/mtd/partitions.h>
     20 
     21 #include <asm/io.h>
     22 
     23 #include <asm/arch/regs-nand.h>
     24 #include <asm/arch/nand.h>
     25 
     26 
     27 struct s3c_nand_regs {
     28     unsigned long nfconf  ;
     29     unsigned long nfcont  ;
     30     unsigned long nfcmd   ;
     31     unsigned long nfaddr  ;
     32     unsigned long nfdata  ;
     33     unsigned long nfeccd0 ;
     34     unsigned long nfeccd1 ;
     35     unsigned long nfeccd  ;
     36     unsigned long nfstat  ;
     37     unsigned long nfestat0;
     38     unsigned long nfestat1;
     39     unsigned long nfmecc0 ;
     40     unsigned long nfmecc1 ;
     41     unsigned long nfsecc  ;
     42     unsigned long nfsblk  ;
     43     unsigned long nfeblk  ;
     44 };
     45 
     46 static struct mtd_info *s3c_mtd;
     47 static struct nand_chip *s3c_nand;
     48 
     49 
     50 static struct mtd_partition s3c_nand_parts[] = {
     51     [0] = {
     52         .name   = "bootloader",
     53         .size   = 0x00040000,
     54         .offset    = 0,
     55     },
     56     [1] = {
     57         .name   = "params",
     58         .offset = MTDPART_OFS_APPEND,
     59         .size   = 0x00020000,
     60     },
     61     [2] = {
     62         .name   = "kernel",
     63         .offset = MTDPART_OFS_APPEND,
     64         .size   = 0x00200000,
     65     },
     66     [3] = {
     67         .name   = "root",
     68         .offset = MTDPART_OFS_APPEND,
     69         .size   = MTDPART_SIZ_FULL,
     70     }
     71 };
     72 
     73 static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
     74 {
     75     if (chipnr == -1)
     76     {
     77         /* 取消选中: NFCONT[1]设为1 */
     78         s3c_nand_regs->nfcont |= (1<<1);        
     79     }
     80     else
     81     {
     82         /* 选中: NFCONT[1]设为0 */
     83         s3c_nand_regs->nfcont &= ~(1<<1);
     84     }
     85 }
     86 
     87 static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
     88 {
     89     if (ctrl & NAND_CLE)
     90     {
     91         /* 发命令: NFCMMD=dat */
     92         s3c_nand_regs->nfcmd = dat;
     93     }
     94     else
     95     {
     96         /* 发地址: NFADDR=dat */
     97         s3c_nand_regs->nfaddr = dat;
     98     }
     99 }
    100 
    101 static int s3c2440_dev_ready(struct mtd_info *mtd)
    102 {
    103     return (s3c_nand_regs->nfstat & (1<<0));
    104 }
    105 
    106 
    107 static int s3c_nand_init(void)
    108 {
    109     struct clk *clk;
    110     s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
    111 
    112     s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
    113 
    114     s3c_nand->select_chip = s3c2440_select_chip;
    115     s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl;
    116     s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata;
    117     s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata;
    118     s3c_nand->dev_ready   = s3c2440_dev_ready;
    119     s3c_nand->ecc.mode    = NAND_ECC_SOFT;//enable ECC
    120     
    121     clk = clk_get(NULL, "nand");
    122     clk_enable(clk);              
    123 
    124 #define TACLS    0
    125 #define TWRPH0   1
    126 #define TWRPH1   0
    127     s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
    128     s3c_nand_regs->nfcont = (1<<1) | (1<<0);
    129     
    130     s3c_mtd = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
    131     s3c_mtd->owner = THIS_MODULE;
    132     s3c_mtd->priv = s3c_nand;
    133     nand_scan(s3c_mtd, 1);//识别nand falsh,构造mtd_info
    134 
    135     add_mtd_partitions(s3c_mtd, s3c_nand_parts,4);
    136 
    137     return 0;
    138 }
    139 
    140 
    141 static void s3c_nand_exit(void)
    142 {
    143     del_mtd_partitions(s3c_mtd);
    144     kfree(s3c_mtd);
    145     iounmap(s3c_nand_regs);
    146     kfree(s3c_nand);
    147 }
    148 
    149 module_init(s3c_nand_init);
    150 module_exit(s3c_nand_exit);
    151 
    152 MODULE_LICENSE("GPL");
    s3c_nand.c
  • 相关阅读:
    C#+Arcengine创建内存图层
    Creating a Feature Set via C#
    ArcGIS Server for JavaScript api安装部署
    Lucene.Net 3.0.3如何从TokenStream中获取token对象
    MMSEG 中文算法说明
    java DotNet char 代码对应
    Lucene.Net 3.0.3如何从TokenStream中获取token对象
    java DotNet char 代码对应
    9.7
    9.6
  • 原文地址:https://www.cnblogs.com/Lwd-linux/p/6283263.html
Copyright © 2020-2023  润新知