·¢²©ÎÄ
fychit´´Òâ¿Õ¼ä

fychit.blog.chinaunix.net

ÕâÀïµÄÎÄÕ»ù±¾¶¼¾­¹ý²âÊÔ£¬¿ÉÒԳɹ¦Ö´ÐУ¬ÈôÓöµ½²»ÄÜÖ´Ðеģ¬ÇëÁôÑÔ£¡ ÈôΪԭ´´£¬ÐèÒª×ªÔØ£¬Çë×¢Ã÷³ö´¦£¡ÈôÓÐÉÌÒµÓÃ;£¬ÇëÒ»¶¨ÓëÎÒÁªÏµ£¡ÈôÓÐÇÖȨ£¬ÇëÓëÎÒÁªÏµ£¡   
¸öÈË×ÊÁÏ
  • ²©¿Í·ÃÎÊ£º91750
  • ²©ÎÄÊýÁ¿£º119
  • ²©¿Í»ý·Ö£º2358
  • ²©¿ÍµÈ¼¶£º´óξ
  • ¹Ø×¢ÈËÆø£º 1
  • ×¢²áʱ¼ä£º2008-11-26 16:07:39
¶©ÔÄÎҵIJ©¿Í
  • ¶©ÔÄ
  • ¶©Ôĵ½Ïʹû
  • ¶©Ôĵ½×¥Ïº
  • ¶©Ôĵ½Google
×ÖÌå´óС£º´ó ÖРС²©ÎÄ


×î½üѧϰÁËNandFlashµÄÇý¶¯£¬Ó²¼þ²Ù×÷·Ç³£¼òµ¥£¬¾ÍÊÇÕâ¸ölinuxϵÄÇý¶¯±È½Ï¸´ÔÓ£¬Ö÷Òª»¹ÊÇMTD²ãµÄÎÊÌ⣬ÓÃÁËÒ»ÏÂÎçʱ¼äÕûÀí³öÀ´Ò»·ÝÏêϸµÄ·ÖÎö£¬Ö»ÊÇ·ÖÎöº¯Êý½á¹¹ºÍµ÷ÓùØÏµ£¬¾ßÌå´úÂëʵÏ־Ͳ»¿´ÁË£¬ÀïÃæÓÐN¸ö½á¹¹Ì壬¸ãµÃÎÒÍ·´ó¡£

 

ÎÒÓÃlinux2.6.25Äںˣ¬2440°å×Ó£¬ÏÈ´ÓÆô¶¯ÐÅÏ¢ÈëÊÖ¡£

ÄÚºËÆô¶¯ÐÅÏ¢£¬NAND²¿·Ö£º

S3C24XX NAND Driver, (c) 2004 Simtec Electronics

s3c2440-nand s3c2440-nand: Tacls=2, 20ns Twrph0=3 30ns, Twrph1=2 20ns

NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)

Scanning device for bad blocks

Creating 3 MTD partitions on "NAND 64MiB 3,3V 8-bit":

0x00000000-0x00040000 : "boot"

0x0004c000-0x0024c000 : "kernel"

0x0024c000-0x03ffc000 : "yaffs2"

 

µÚÒ»ÐУ¬ÔÚdriver/mtd/nand/s3c2410.cÖеÚ910ÐУ¬s3c2410_nand_initº¯Êý£º

printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics/n");

 

ÐжþÐУ¬Í¬Ò»Îļþ£¬µÚ212ÐУ¬s3c2410_nand_inithwº¯Êý£º

dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns/n", tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));

 

µÚÈýÐУ¬ÔÚdriver/mtd/nand/nand_base.cÖеÚ2346ÐУ¬

printk(KERN_INFO "NAND device: Manufacturer ID:" " 0x%02x, Chip ID: 0x%02x (%s %s)/n", *maf_id, dev_id, nand_manuf_ids[maf_idx].name, type->name);

 

µÚËÄÐУ¬ÔÚdriver/mtd/nand/nand_bbt.cÖеÚ380ÐУ¬creat_bbtº¯Êý£º

Printk(KERN INFO " Scanning device for bad blocks /n");

 

µÚÎåÐУ¬ÔÚdriver/mtd/mtdpart.cÖеÚ340ÐУ¬add_mtd_partitionsº¯Êý£º

printk (KERN_NOTICE "Creating %d MTD partitions on /"%s/":/n", nbparts, master->name);

 

ÏÂÃæÈýÐУ¬ÊÇflash·ÖÇø±í£¬Ò²ÔÚmtdpart.cͬһº¯ÊýÖУ¬µÚ430ÐУº

printk (KERN_NOTICE "0x%08x-0x%08x : /"%s/"/n", slave->offset, slave->offset + slave->mtd.size, slave->mtd.name);

 

MTDÌåϵ½á¹¹£º

ÔÚlinuxÖÐÌṩÁËMTD£¨Memory Technology Device£¬ÄÚ´æ¼¼ÊõÉ豸£©ÏµÍ³À´½¨Á¢FlashÕë¶ÔlinuxµÄͳһ¡¢³éÏóµÄ½Ó¿Ú

ÒýÈëMTDºó£¬linuxϵͳÖеÄFlashÉ豸Çý¶¯¼°½Ó¿Ú¿É·ÖΪ4²ã:

É豸½Úµã

MTDÉ豸²ã

MTDԭʼÉ豸²ã

Ó²¼þÇý¶¯²ã

 

Ó²¼þÇý¶¯²ã£ºFlashÓ²¼þÇý¶¯²ã¸ºÔðµ×²ãÓ²¼þÉ豸ʵ¼ÊµÄ¶Á¡¢Ð´¡¢²Á³ý£¬Linux MTDÉ豸µÄNANDÐÍFlashÇý¶¯Î»ÓÚdriver/mtd/nand×ÓĿ¼ÏÂ

s3c2410¶ÔÓ¦µÄnand FlashÇý¶¯Îªs3c2410.c

MTDԭʼÉ豸²ã£ºMTDԭʼÉ豸²ãÓÉÁ½²¿·Ö¹¹³É£¬Ò»²¿·ÖÊÇMTDԭʼÉ豸µÄͨÓôúÂ룬ÁíÒ»²¿·ÖÊǸ÷¸öÌØ¶¨FlashµÄÊý¾Ý£¬±ÈÈç·ÖÇø

Ö÷Òª¹¹³ÉµÄÎļþÓУº

drivers/mtd/mtdcore.c Ö§³Ömtd×Ö·ûÉ豸

driver/mtd/mtdpart.c  Ö§³Ömtd¿éÉ豸

MTDÉ豸²ã£º»ùÓÚMTDԭʼÉ豸£¬Linuxϵͳ¿ÉÒÔ¶¨Òå³öMTDµÄ¿éÉ豸£¨Ö÷É豸ºÅ31) ºÍ×Ö·ûÉ豸£¨É豸ºÅ90£©£¬¹¹³ÉMTDÉ豸²ã

 

¼òµ¥µÄ˵¾ÍÊÇ£ºÊ¹ÓÃÒ»¸ömtd²ãÀ´×÷Ϊ¾ßÌåµÄÓ²¼þÉ豸Çý¶¯ºÍÉϲãÎļþϵͳµÄÇÅÁº¡£mtd¸ø³öÁËϵͳÖÐËùÓÐmtdÉ豸£¨nand£¬nor£¬diskonchip£©µÄͳһ×éÖ¯·½Ê½¡£

 

mtd²ãÓÃÒ»¸öÊý×éstruct mtd_info *mtd_table[MAX_MTD_DEVICES]±£´æÏµÍ³ÖÐËùÓеÄÉ豸£¬mtdÉ豸ÀûÓÃstruct mtd_info Õâ¸ö½á¹¹À´ÃèÊö£¬¸Ã½á¹¹ÖÐÃèÊöÁË´æ´¢É豸µÄ»ù±¾ÐÅÏ¢ºÍ¾ßÌå²Ù×÷ËùÐèÒªµÄÄں˺¯Êý£¬mtdϵͳµÄÄǸö»úÖÆÖ÷Òª¾ÍÊÇÎ§ÈÆÕâ¸ö½á¹¹À´ÊµÏֵġ£½á¹¹ÌåÔÚinclude/linux/mtd/mtd.hÖж¨Ò壺

struct mtd_info {

u_char type;            //MTD É豸ÀàÐÍ

u_int32_t flags;        //MTDÉ豸ÊôÐÔ±êÖ¾

u_int32_t size;         //±êʾÁËÕâ¸ömtdÉ豸µÄ´óС

u_int32_t erasesize;    //MTDÉ豸µÄ²Á³ýµ¥Ôª´óС£¬¶ÔÓÚNandFlashÀ´Ëµ¾ÍÊÇBlockµÄ´óС

u_int32_t oobblock;      //oobÇøÔÚÒ³ÄÚµÄλÖ㬶ÔÓÚ512×Ö½ÚÒ»Ò³µÄnandÀ´ËµÊÇ512

u_int32_t oobsize;      //oobÇøµÄ´óС£¬¶ÔÓÚ512×Ö½ÚÒ»Ò³µÄnandÀ´ËµÊÇ16

u_int32_t ecctype;      //eccУÑéÀàÐÍ

u_int32_t eccsize;      //eccµÄ´óС

 

char *name;             //É豸µÄÃû×Ö

int index;              //É豸ÔÚMTDÁбíÖеÄλÖÃ

 

struct nand_oobinfo oobinfo; //oobÇøµÄÐÅÏ¢£¬°üÀ¨ÊÇ·ñʹÓÃecc£¬eccµÄ´óС

 

//ÒÔÏÂÊǹØÓÚmtdµÄһЩ¶Áдº¯Êý£¬½«ÔÚnand_baseÖеÄnand_scanÖÐÖØÔØ

int (*erase)

int (*read)

int (*write)

int (*read_ecc)

int (*write_ecc)

int (*read_oob)

int (*read_oob)

 

void *priv;//É豸˽ÓÐÊý¾ÝÖ¸Õ룬¶ÔÓÚNandFlashÀ´ËµÖ¸nandоƬµÄ½á¹¹

 

ÏÂÃæ¿´nand_chip½á¹¹£¬ÔÚinclude/linux/mtd/nand.hÖж¨Ò壺

struct nand_chip {

void  __iomem   *IO_ADDR_R;    //ÕâÊÇnandflashµÄ¶Áд¼Ä´æÆ÷

void  __iomem     *IO_ADDR_W; 

//ÒÔ϶¼ÊÇnandflashµÄ²Ù×÷º¯Êý£¬ÕâЩº¯Êý½«¸ù¾ÝÏàÓ¦µÄÅäÖýøÐÐÖØÔØ

u_char    (*read_byte)(struct mtd_info *mtd);

void      (*write_byte)(struct mtd_info *mtd, u_char byte);

u16       (*read_word)(struct mtd_info *mtd);

void      (*write_word)(struct mtd_info *mtd, u16 word);

void     (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);

void     (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);

int     (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);

void     (*select_chip)(struct mtd_info *mtd, int chip);

int     (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);

int      (*block_markbad)(struct mtd_info *mtd, loff_t ofs);

void     (*hwcontrol)(struct mtd_info *mtd, int cmd);

int      (*dev_ready)(struct mtd_info *mtd);

void     (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);

int      (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);

int     (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);

int   (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);

void    (*enable_hwecc)(struct mtd_info *mtd, int mode);

void    (*erase_cmd)(struct mtd_info *mtd, int page);

int     (*scan_bbt)(struct mtd_info *mtd);

int       eccmode;     //eccµÄУÑéģʽ£¨Èí¼þ£¬Ó²¼þ£©

int       chip_delay;  //оƬʱÐòÑÓ³Ù²ÎÊý

int       page_shift;  //Ò³Æ«ÒÆ£¬¶ÔÓÚ512B/Ò³µÄ£¬Ò»°ãÊÇ9

u_char    *data_buf;   //Êý¾Ý»º´æÇø

 

¸úNAND²Ù×÷Ïà¹ØµÄº¯Êý£º

1¡¢ nand_base.c£º

¶¨ÒåÁËNANDÇý¶¯ÖжÔNANDоƬ×î»ù±¾µÄ²Ù×÷º¯ÊýºÍ²Ù×÷Á÷³Ì£¬Èç²Á³ý¡¢¶Áдpage¡¢¶ÁдoobµÈ¡£µ±È»ÕâЩº¯Êý¶¼Ö»ÊǽøÐÐһЩ³£¹æµÄ²Ù×÷£¬ÈôÄãµÄϵͳÔÚ¶ÔNAND²Ù×÷ʱÓÐÒ»Ð©ÌØÊâµÄ¶¯×÷£¬ÔòÐèÒªÔÚÄã×Ô¼ºµÄÇý¶¯´úÂëÖнøÐж¨Òå¡£

2¡¢ nand_bbt.c£º

¶¨ÒåÁËNANDÇý¶¯ÖÐÓ뻵¿é¹ÜÀíÓйصĺ¯ÊýºÍ½á¹¹Ìå¡£

3¡¢ nand_ids.c£º

¶¨ÒåÁËÁ½¸öÈ«¾ÖÀàÐ͵ĽṹÌ壺struct nand_flash_dev nand_flash_ids[ ]ºÍstruct nand_manufacturers nand_manuf_ids[ ]¡£ÆäÖÐǰÕß¶¨ÒåÁËһЩNANDоƬµÄÀàÐÍ£¬ºóÕß¶¨ÒåÁËNANDоƬµÄ¼¸¸ö³§ÉÌ¡£NANDоƬµÄIDÖÁÉÙ°üº¬Á½ÏîÄÚÈÝ£º³§ÉÌIDºÍ³§ÉÌΪ×Ô¼ºµÄNANDоƬ¶¨ÒåµÄоƬID¡£µ±NAND¼ÓÔØÊ±»áÕÒÕâÁ½¸ö½á¹¹Ì壬¶Á³öID£¬Èç¹ûÕÒ²»µ½£¬¾Í»á¼ÓÔØÊ§°Ü¡£

4¡¢ nand_ecc.c£º

¶¨ÒåÁËNANDÇý¶¯ÖÐÓësofteware ECCÓйصĺ¯ÊýºÍ½á¹¹Ì壬ÈôÄãµÄϵͳ֧³Öhardware ECC£¬ÇÒ²»ÐèÒªsoftware ECC£¬Ôò¸ÃÎļþÒ²²»ÐèÀí»á¡£

 

ÎÒÃÇÐèÒª¹ØÐĵÄÊÇ/nand/s3c2410,Õâ¸öÎļþʵÏÖµÄÊÇs3c2410/2440nandflash¿ØÖÆÆ÷×î»ù±¾µÄÓ²¼þ²Ù×÷£¬¶Áд²Á³ý²Ù×÷ÓÉÉϲ㺯ÊýÍê³É¡£

s3c2410.c·ÖÎö£º

Ê×ÏÈ¿´Ò»ÏÂÒªÓõ½µÄ½á¹¹ÌåµÄ×¢²á£º

struct s3c2410_nand_mtd {

    struct mtd_info      mtd;   //mtd_infoµÄ½á¹¹Ìå

    struct nand_chip     chip;  //nand_chipµÄ½á¹¹Ìå

    struct s3c2410_nand_set     *set;

    struct s3c2410_nand_info    *info;

    int           scan_res;

};

 

enum s3c_cpu_type {  //ÓÃÀ´Ã¶¾ÙCPUÀàÐÍ

    TYPE_S3C2410,

    TYPE_S3C2412,

    TYPE_S3C2440,

};

struct s3c2410_nand_info { 

    /* mtd info */

    struct nand_hw_control      controller;

    struct s3c2410_nand_mtd     *mtds;

    struct s3c2410_platform_nand    *platform;

 

    /* device info */

    struct device        *device;

    struct resource          *area;

    struct clk        *clk;

    void __iomem         *regs;

    void __iomem         *sel_reg;

    int           sel_bit;

    int           mtd_count;

    unsigned long        save_nfconf;

    enum s3c_cpu_type    cpu_type;

};

 

É豸µÄ×¢²á£º

static int __init s3c2410_nand_init(void)

{

    printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics/n");

 

    platform_driver_register(&s3c2412_nand_driver);

    platform_driver_register(&s3c2440_nand_driver);

    return platform_driver_register(&s3c2410_nand_driver);

}

platform_driver_registerÏòÄÚºË×¢²áÉ豸£¬Í¬Ê±Ö§³ÖÕâÈýÖÖCPU¡£

&s3c2440_nand_driverÊÇÒ»¸öplatform_driverÀàÐ͵ĽṹÌ壺

 

static struct platform_driver s3c2440_nand_driver = {

    .probe     = s3c2440_nand_probe,

    .remove   = s3c2410_nand_remove,

    .suspend   = s3c24xx_nand_suspend,

    .resume    = s3c24xx_nand_resume,

    .driver    = {

       .name  = "s3c2440-nand",

       .owner = THIS_MODULE,

    },

};

 

×îÖ÷ÒªµÄº¯Êý¾ÍÊÇs3c2440_nand_probe£¬£¨µ÷ÓÃs3c24XX_nand_probe£©,Íê³É¶ÔnandÉ豸µÄ̽²â£¬

static int s3c24xx_nand_probe(struct platform_device *pdev,

                 enum s3c_cpu_type cpu_type)

{

       /*Ö÷ÒªÍê³ÉһЩӲ¼þµÄ³õʼ»¯£¬ÆäÖе÷Óú¯Êý£º*/

       s3c2410_nand_init_chip(info, nmtd, sets);

       /*init_chip½áÊøºó£¬µ÷ÓÃnand_scanÍê³É¶ÔflashµÄ̽²â¼°mtd_info¶Áдº¯ÊýµÄ¸³Öµ*/

nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);

       if (nmtd->scan_res == 0) {

           s3c2410_nand_add_partition(info, nmtd, sets);

       }

}

Nand_scanÊÇÔÚ³õʼ»¯nandµÄʱºò¶Ônand½øÐеÄÒ»²½·Ç³£ºÃÖØÒªµÄ²Ù×÷£¬ÔÚnand_scanÖлá¶ÔÎÒÃÇËùдµÄ¹ØÓÚÌØ¶¨Ð¾Æ¬µÄ¶Áдº¯ÊýÖØÔØµ½nand_chip½á¹¹ÖÐÈ¥£¬²¢»á½«mtd_info½á¹¹ÌåÖеĺ¯ÊýÓÃnandµÄº¯ÊýÀ´ÖØÔØ£¬ÊµÏÖÁËmtdµ½µ×²ãÇý¶¯µÄÁªÏµ¡£

²¢ÇÒÔÚnand_scanº¯ÊýÖлáͨ¹ý¶ÁÈ¡nandоƬµÄÉ豸ºÅºÍ³§¼ÒºÅ×Ô¶¯ÔÚоƬÁбíÖÐѰÕÒÏàÓ¦µÄÐͺźͲÎÊý£¬²¢½«Æä×¢²á½øÈ¥¡£

 

 

static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,

                 struct s3c2410_nand_mtd *nmtd,

                 struct s3c2410_nand_set *set)

{

    struct nand_chip *chip = &nmtd->chip;

    void __iomem *regs = info->regs;

    /*ÒÔ϶¼ÊǶÔchip¸³Öµ£¬¶ÔÓ¦nand_chipÖеĺ¯Êý*/

    chip->write_buf    = s3c2410_nand_write_buf;  //дbuf

    chip->read_buf     = s3c2410_nand_read_buf;   //¶Ábuf

    chip->select_chip  = s3c2410_nand_select_chip;//Ƭѡ

    chip->chip_delay   = 50;

    chip->priv    = nmtd;

    chip->options    = 0;

    chip->controller   = &info->controller; //£¿£¿

 

    switch (info->cpu_type) {

    case TYPE_S3C2440:

       chip->IO_ADDR_W = regs + S3C2440_NFDATA;  //Êý¾Ý¼Ä´æÆ÷

       info->sel_reg   = regs + S3C2440_NFCONT;  //¿ØÖƼĴæÆ÷

       info->sel_bit = S3C2440_NFCONT_nFCE;

       chip->cmd_ctrl  = s3c2440_nand_hwcontrol; //Ó²¼þ¿ØÖÆ

       chip->dev_ready = s3c2440_nand_devready;  //É豸¾ÍÐ÷

       chip->read_buf  = s3c2440_nand_read_buf;  //¶Ábuf

       chip->write_buf   = s3c2440_nand_write_buf;//дbuf

       break;

    }

    chip->IO_ADDR_R = chip->IO_ADDR_W; //¶Áд¼Ä´æÆ÷¶¼ÊÇͬһ¸ö

    nmtd->info    = info;

    nmtd->mtd.priv       = chip; //˽ÓÐÊý¾ÝÖ¸ÕëÖ¸Ïòchip

    nmtd->mtd.owner    = THIS_MODULE;

    nmtd->set     = set;

    /*ºóÃæÊǺÍECCУÑéÓйصģ¬Ê¡ÂÔ*/

}

 

³õʼ»¯ºó£¬ÊµÏÖ¶ÔnandµÄ»ù±¾Ó²¼þ²Ù×÷¾Í¿ÉÒÔÁË£¬°üÀ¨ÒÔϺ¯Êý£º

s3c2410_nand_inithw  //³õʼ»¯Ó²¼þ£¬ÔÚprobeÖе÷ÓÃ

s3c2410_nand_select_chip  //Ƭѡ

s3c2440_nand_hwcontrol  //Ó²¼þ¿ØÖÆ£¬Æäʵ¾ÍÊÇÆ¬Ñ¡

s3c2440_nand_devready  //É豸¾ÍÐ÷

s3c2440_nand_enable_hwecc  //ʹÄÜÓ²¼þECCУÑé

s3c2440_nand_calculate_ecc  //¼ÆËãECC

s3c2440_nand_read_buf  s3c2440_nand_write_buf

 

×¢²ánandÉ豸µ½MTDԭʼÉ豸²ã£º£¨Õâ¸öº¯ÊýÓÉprobeµ÷Óã©

#ifdef CONFIG_MTD_PARTITIONS   //Èç¹û¶¨ÒåÁËMTD·ÖÇø

static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,

                    struct s3c2410_nand_mtd *mtd,

                    struct s3c2410_nand_set *set)

{

    if (set == NULL)

       return add_mtd_device(&mtd->mtd);

    if (set->nr_partitions > 0 && set->partitions != NULL) {

       return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);

    }

    return add_mtd_device(&mtd->mtd);

}

#else

×¢²áÉ豸ÓÃÕâÁ½¸öº¯Êý£º

add_mtd_device  //Èç¹ûnandÕûÌå²»·ÖÇø£¬ÓÃÕâ¸ö£¬

//¸Ãº¯ÊýÔÚmtdcore.cÖÐʵÏÖ

add_mtd_partitions  //Èç¹ûnandÊÇ·ÖÇø½á¹¹£¬ÓÃÕâ¸ö£¬

//¸Ãº¯ÊýÔÚmtdpart.cÖÐʵÏÖ

ͬÑù£¬×¢ÏúÉ豸ҲÓÐÁ½¸öº¯Êý£º

del_mtd_device

del_mtd_partitions

 

NandFlash»¹ÓÐÒ»¸ö·ÖÇø±í½á¹¹Ì壬mtd_partition£¬Õâ¸öÊÇÔÚarch/arm/plat-s3c24XX/common-smdk.cÖж¨ÒåµÄ¡£

 

static struct mtd_partition smdk_default_nand_part[] = {

    [0] = {

       .name  = "boot",

       .size  = 0x00040000,

       .offset    = 0,

    },

    [1] = {

       .name  = "kernel",

       .offset = 0x0004C000,

       .size  = 0x00200000,

    },

    [2] = {

       .name  = "yaffs2",

       .offset = 0x0024C000,

       .size  = 0x03DB0000,

    },

};

¼Ç¼Á˵±Ç°µÄnand flashÓм¸¸ö·ÖÇø£¬Ã¿¸ö·ÖÇøµÄÃû×Ö£¬´óС£¬Æ«ÒÆÁ¿ÊǶàÉÙ

ϵͳ¾ÍÊÇÒÀ¿¿ÕâЩ·ÖÇø±íÕÒµ½¸÷¸öÎļþϵͳµÄ

ÕâЩ·ÖÇø±ínandÖеÄÎļþϵͳûÓбØÈ»¹ØÏµ£¬·ÖÇø±íÖ»ÊǰÑflash·Ö³É²»Í¬µÄ²¿·Ö

 

Èç¹û×Ô¼º±àдһ¸önandflashÇý¶¯£¬Ö»ÐèÒªÌî³äÕâÈý¸ö½á¹¹Ì壺

Mtd_info     nand_chip     mtd_partition

²¢ÊµÏÖ¶ÔÎïÀíÉ豸µÄ¿ØÖÆ£¬ÉϲãµÄÇý¶¯¿ØÖÆÒÑÓÉmtd×öºÃÁË£¬²»ÐèÒª¹ØÐÄ

 

2410NandFlash¿ØÖÆÆ÷

¹Ü½ÅÅäÖÃ

D[7:0]: DATA0-7 Êý¾Ý/ÃüÁî/µØÖ·/µÄÊäÈë/Êä³ö¿Ú£¨ÓëÊý¾Ý×ÜÏß¹²Ïí£©

CLE : GPA17  ÃüÁîËø´æÊ¹ÄÜ (Êä³ö)

ALE : GPA18  µØÖ·Ëø´æÊ¹ÄÜ£¨Êä³ö£©

nFCE : GPA22 NAND Flash Æ¬Ñ¡Ê¹ÄÜ£¨Êä³ö£©

nFRE : GPA20 NAND Flash ¶ÁʹÄÜ (Êä³ö)

nFWE : GPA19 NAND Flash Ð´Ê¹ÄÜ (Êä³ö)

R/nB : GPA21 NAND Flash ×¼±¸ºÃ/·±Ã¦£¨ÊäÈ룩

 

Ïà¹Ø¼Ä´æÆ÷£º

NFCONF   NandFlash¿ØÖƼĴæÆ÷

 £Û15£ÝNandFlash¿ØÖÆÆ÷ʹÄÜ/½ûÖ¹     0 = ½ûÖ¹   1 = Ê¹ÄÜ

 £Û14£º13£Ý±£Áô

 £Û12£Ý³õʼ»¯ECC½âÂëÆ÷/±àÂëÆ÷    0 = ²»³õʼ»¯   1 = ³õʼ»¯

 £Û11£ÝоƬʹÄÜ  nFCE¿ØÖÆ        0 = Ê¹ÄÜ       1 = ½ûÖ¹

 £Û10£º8£ÝTACLS   ³ÖÐøÊ±¼ä = HCLK*£¨TACLS+1£©

 £Û6£º4£Ý TWRPH0

 £Û2£º0£Ý TWRPH1

 

NFCMD  ÃüÁîÉèÖüĴæÆ÷

 £Û7£º0£Ý ÃüÁîÖµ

NFADDR µØÖ·ÉèÖüĴæÆ÷

 £Û7£º0£Ý ´æ´¢Æ÷µØÖ·

NFDATA Êý¾Ý¼Ä´æÆ÷

 £Û7£º0£Ý ´æ·ÅÊý¾Ý

NFSTAT ×´Ì¬¼Ä´æÆ÷

 £Û0£Ý    0 = ´æ´¢Æ÷æ     1 = ´æ´¢Æ÷×¼±¸ºÃ

NFECC  ECC¼Ä´æÆ÷

 £Û23£º16£ÝECCУÑéÂë2

 £Û15£º8£Ý ECCУÑéÂë1

 £Û8£º0£Ý  ECCУÑéÂë0

 

д²Ù×÷£º

дÈë²Ù×÷ÒÔҳΪµ¥Î»¡£Ð´Èë±ØÐëÔÚ²Á³ýÖ®ºó£¬·ñÔòдÈ뽫³ö´í¡£

ҳдÈëÖÜÆÚÖаüÀ¨ÒÔϲ½Ö裺

дÈë´®ÐÐÊý¾ÝÊäÈëÖ¸Á80h£©¡£È»ºóдÈë4¸ö×ֽڵĵØÖ·£¬×îºó´®ÐÐдÈëÊý¾Ý£¨528Byte£©¡£´®ÐÐдÈëµÄÊý¾Ý×î¶àΪ528byte¡£

´®ÐÐÊý¾ÝдÈëÍê³Éºó£¬ÐèҪдÈ롰ҳдÈëÈ·ÈÏ¡±Ö¸Áî10h£¬ÕâÌõÖ¸Á³õʼ»¯Æ÷¼þÄÚ²¿Ð´Èë²Ù×÷¡£

10hдÈëÖ®ºó£¬nand flashµÄÄÚ²¿Ð´¿ØÖÆÆ÷½«×Ô¶¯Ö´ÐÐÄÚ²¿Ð´ÈëºÍУÑéÖбØÒªµÄËã·¨ºÍʱÐò£¬

ϵͳ¿ÉÒÔͨ¹ý¼ì²âR/BµÄÊä³ö£¬»ò¶Á״̬¼Ä´æÆ÷µÄ״̬루I/O 6£©À´ÅжÏÄÚ²¿Ð´ÈëÊÇ·ñ½áÊø

 

²Á³ý²Ù×÷£º

²Á³ý²Ù×÷ʱÒÔ¿é(16K Byte)Ϊµ¥Î»½øÐеÄ

²Á³ýµÄÆô¶¯Ö¸ÁîΪ60h,ËæºóµÄ3¸öʱÖÓÖÜÆÚÊÇ¿éµØÖ·¡£ÆäÖÐÖ»ÓÐA14µ½A25ÊÇÓÐЧµÄ£¬¶øA9µ½A13ÊÇ¿ÉÒÔºöÂԵġ£

¿éµØÖ·Ö®ºóÊDzÁ³ýÈ·ÈÏÖ¸ÁîD0h£¬ÓÃÀ´¿ªÊ¼ÄÚ²¿µÄ²Á³ý²Ù×÷¡£

Æ÷¼þ¼ì²âµ½²Á³ýÈ·ÈÏÃüÁîºó£¬ÔÚ/WEµÄÉÏÉýÑØÆô¶¯ÄÚ²¿Ð´¿ØÖÆÆ÷£¬¿ªÊ¼Ö´ÐвÁ³ýºÍ²Á³ýУÑé¡£ÄÚ²¿²Á³ý²Ù×÷Íê³Éºó£¬Ó¦¸Ã¼ì²âд״̬루I/O 0£©£¬´Ó¶øÁ˽â²Á³ý²Ù×÷ÊÇ·ñ³É¹¦Íê³É¡£

 

¶Á²Ù×÷ÓÐÁ½ÖÖ¶Áģʽ£º

¶Á·½Ê½1ÓÃÓÚ¶ÁÕý³£Êý¾Ý£»

¶Á·½Ê½2ÓÃÓÚ¶Á¸½¼ÓÊý¾Ý

ÔÚ³õʼÉϵçʱ£¬Æ÷¼þ½øÈëȱʡµÄ¡°¶Á·½Ê½1ģʽ¡±¡£ÔÚÕâһģʽÏ£¬Ò³¶ÁÈ¡²Ù×÷ͨ¹ý½«00hÖ¸ÁîдÈëÖ¸Áî¼Ä´æÆ÷£¬½Ó×ÅдÈë3¸öµØÖ·£¨Ò»¸öÁеØÖ·ºÍ2¸öÐеØÖ·£©À´Æô¶¯¡£Ò»µ©Ò³¶ÁÖ¸Áî±»Æ÷¼þËø´æ£¬ÏÂÃæµÄÒ³²Ù×÷¾Í²»ÐèÒªÔÙÖØ¸´Ð´ÈëÖ¸ÁîÁË¡£

дÈëÖ¸ÁîºÍµØÖ·ºó£¬´¦ÀíÆ÷¿ÉÒÔͨ¹ý¶ÔÐźÅÏßR//BµÄ·ÖÎöÀ´ÅжϸòÅ×÷ÊÇ·ñÍê³É¡£

Íⲿ¿ØÖÆÆ÷¿ÉÒÔÔÙÒÔ50nsΪÖÜÆÚµÄÁ¬Ðø/REÂö³åÐźŵĿØÖÆÏ£¬´ÓI/O¿ÚÒÀ´Î¶Á³öÊý¾Ý

±¸ÓÃÇøÓòµÄ´Ó512µ½527µØÖ·µÄÊý¾Ý£¬¿ÉÒÔͨ¹ý¶Á·½Ê½2Ö¸Áî½øÐÐÖ¸Áî½øÐжÁÈ¡£¨ÃüÁîΪ50h£©¡£µØÖ·A0¡«A3ÉèÖÃÁ˱¸ÓÃÇøÓòµÄÆðʼµØÖ·£¬A4¡«A7±»ºöÂÔµô

 

ʱÐòÒªÇó£º

дµØÖ·¡¢Êý¾Ý¡¢ÃüÁîʱ£¬nCE¡¢nWEÐźűØÐëΪµÍµçƽ£¬ËüÃÇÔÚnWEÐźŵÄÉÏÉýÑØ±»Ëø´æ¡£ÃüÁîËø´æÊ¹ÄÜÐźÅCLEºÍµØÖ·Ëø´æÐźÅALEÓÃÀ´Çø·ÖI/OÒý½ÅÉÏ´«ÊäµÄÊÇÃüÁÊǵØÖ·¡£

 

Ѱַ·½Ê½£º

NAND FlashµÄѰַ·½Ê½ºÍNAND FlashµÄmemory×éÖ¯·½Ê½½ôÃÜÏà¹Ø¡£NAND FlashµÄÊý¾ÝÒÔbitµÄ·½Ê½±£´æÔÚmemory cell£¬Ò»¸öcellÖÐÖ»ÄÜ´æ´¢Ò»¸öbit¡£ÕâЩcellÒÔ8¸ö»òÕß16¸öΪµ¥Î»£¬Á¬³Ébit line£¬ÐγÉbyte(x8)/word(x16)£¬Õâ¾ÍÊÇNANDµÄÊý¾Ý¿í¶È¡£

      

       ÕâЩLine»áÔÙ×é³ÉPage£¬µäÐÍÇé¿öÏ£ºÍ¨³£ÊÇ528Byte/page»òÕß264Word/page¡£È»ºó£¬Ã¿32¸öpageÐγÉÒ»¸öBlock£¬Sizeof(block)=16.5kByte¡£ÆäÖÐ528Byte = 512Byte+16Byte£¬Ç°512ByteΪÊý¾ÝÇø£¬ºó16Byte´æ·ÅÊý¾ÝУÑéÂëµÈ£¬Òò´Ëϰ¹ßÉÏÈËÃdzÆ1pageÓÐ512¸ö×Ö½Ú£¬Ã¿¸öBlockÓÐ16Kbytes£»

      ÏÖÔÚÔÚһЩ´óÈÝÁ¿µÄFLASH´æÖüÉ豸ÖÐÒ²²ÉÓÃÒÔÏÂÅäÖãº2112 Byte /page »ò 1056 Word/page£»64page/Block£»Sizeof(block) = 132kByte£»Í¬ÉÏ£º2112 = 2048 +64£¬ÈËÃÇϰ¹ß³ÆÒ»Ò³º¬2k¸ö×Ö½Ú£¬Ò»¸öBlockº¬ÓÐ64¸öÒ³£¬ÈÝÁ¿Îª128KB£»

 

       BlockÊÇNAND FlashÖÐ×î´óµÄ²Ù×÷µ¥Ôª£¬²Á³ý¿ÉÒÔ°´ÕÕblock»òpageΪµ¥Î»Íê³É£¬¶ø±à³Ì/¶ÁÈ¡Êǰ´ÕÕpageΪµ¥Î»Íê³ÉµÄ

¡£

       ËùÒÔ£¬°´ÕÕÕâÑùµÄ×éÖ¯·½Ê½¿ÉÒÔÐγÉËùνµÄÈýÀàµØÖ·£º

         -Block  Address   ¿éµØÖ·

         -Page   Address   Ò³µØÖ·

         -Column Address  ÁеØÖ·

      Ê×ÏÈ£¬±ØÐëÇå³þÒ»µã£¬¶ÔÓÚNAND FlashÀ´½²£¬µØÖ·ºÍÃüÁîÖ»ÄÜÔÚI/O[7:0]ÉÏ´«µÝ£¬Êý¾Ý¿í¶È¿ÉÒÔÊÇ8λ»òÕß16룬µ«ÊÇ£¬¶ÔÓÚx16µÄNAND Device£¬I/O[15:8]Ö»ÓÃÓÚ´«µÝÊý¾Ý¡£

    Çå³þÁËÕâÒ»µã£¬ÎÒÃǾͿÉÒÔ¿ªÊ¼·ÖÎöNAND FlashµÄѰַ·½Ê½ÁË¡£

ÒÔ528Byte/page ×ÜÈÝÁ¿64M Byte+512kbyteµÄNANDÆ÷¼þΪÀý£º

ÒòΪ

1page=528byte=512byte(Main Area)+16byte(Spare Area)

1block=32page = 16kbyte

64Mbyte = 4096 Block

 

Óû§Êý¾Ý±£´æÔÚmain areaÖС£

512byteÐèÒª9bitÀ´±íʾ£¬¶ÔÓÚ528byteϵÁеÄNAND£¬Õâ512byte±»·Ö³É1st halfºÍ2nd half,¸÷×ԵķÃÎÊÓÉËùνµÄpointer operationÃüÁîÀ´Ñ¡Ôñ£¬Ò²¾ÍÊÇÑ¡ÔñÁËbit8µÄ¸ßµÍ¡£Òò´ËA8¾ÍÊÇhalfpage pointer£¬A[7:0]¾ÍÊÇËùνµÄcolumn address¡£

 

32¸öpageÐèÒª5bitÀ´±íʾ£¬Õ¼ÓÃA[13:9]£¬¼´¸ÃpageÔÚ¿éÄÚµÄÏà¶ÔµØÖ·¡£

BlockµÄµØÖ·ÊÇÓÉA14ÒÔÉϵÄbitÀ´±íʾ£¬ÀýÈç64MBµÄNAND£¬¹²4096block£¬Òò´Ë£¬ÐèÒª12¸öbitÀ´±íʾ£¬¼´A[25:14]£¬Èç¹ûÊÇ1GbitµÄ528byte/pageµÄNAND Flash£¬¹²8192¸öblock£¬Ôòblock addressÓÃA[30:14]±íʾ¡£

 

NAND FlashµÄµØÖ·±íʾΪ£º

Block Address  |  Page Address in block  |  half page pointer |  Column Address

µØÖ·´«ËÍ˳ÐòÊÇColumn Address , Page Address , Block Address¡£

 

ÀýÈçÒ»¸öµØÖ·£º0x00aa55aa

         0000 0000  1010  1010  0101  0101  1010  1010

 

ÓÉÓÚµØÖ·Ö»ÄÜÔÚI/O[7:0]ÉÏ´«µÝ£¬Òò´Ë£¬±ØÐë²ÉÓÃÒÆÎ»µÄ·½Ê½½øÐС£

ÀýÈ磬¶ÔÓÚ64MBx8µÄNAND flash£¬µØÖ··¶Î§ÊÇ0~0x3FF_FFFF£¬Ö»ÒªÊÇÕâ¸ö·¶Î§ÄÚµÄÊýÖµ±íʾµÄµØÖ·¶¼ÊÇÓÐЧµÄ¡£

      

       ÒÔNAND_ADDRΪÀý£º

       µÚ1²½ÊÇ´«µÝcolumn address£¬¾ÍÊÇNAND_ADDR[7:0]£¬²»ÐèÒÆÎ»¼´¿É´«µÝµ½I/O[7:0]ÉÏ£¬ ¶øhalfpage pointer¼´bit8ÊÇÓɲÙ×÷Ö¸Áî¾ö¶¨µÄ£¬¼´Ö¸Áî¾ö¶¨ÔÚÄĸöhalfpageÉϽøÐжÁд£¬¶øÕæÕýµÄbit8µÄÖµÊÇdon't careµÄ¡£

       µÚ2²½¾ÍÊǽ«NAND_ADDRÓÒÒÆ9룬½«NAND_ADDR[16:9]´«µ½I/O[7:0]ÉÏ;

       µÚ3²½½«NAND_ADDR[24:17]·Åµ½I/OÉÏ;

       µÚ4²½ÐèÒª½«NAND_ADDR[25]·Åµ½I/OÉÏ;

       Òò´Ë£¬Õû¸öµØÖ·´«µÝ¹ý³ÌÐèÒª4²½²ÅÄÜÍê³É£¬¼´4-step addressing¡£

       Èç¹ûNAND FlashµÄÈÝÁ¿ÊÇ32MBÒÔÏ£¬ÄÇô£¬block adress×î¸ßλֻµ½bit24£¬Òò´ËѰַֻÐèÒª3²½¡£

²©¿ÍÍÆ¼öÎÄÕÂ
Ç×£¬Äú»¹Ã»ÓеǼ,Çë[µÇ¼]»ò[×¢²á]ºóÔÙ½øÐÐÆÀÂÛ