NandFlash底层代码的修改
u-boot_2010.6nandflash驱动彻底分析
u-boot_2010.6nandflash驱动彻底分析2017年11⽉13⽇15:37:34最近公司⼤裁员,闹的⼈⼼惶惶,不管怎么样,武装好⾃⼰才是硬道理,坚持学习,学会那些还没学会的。
今天虚拟机突然打不开了,吓了我⼀跳,因为代码都还没备份,⼀定得养成备份代码的习惯!好了,下⾯开始进⼊正题吧,nandflash驱动彻底分析底层驱动移植完后,执⾏nand 命令:nand read 0x30000000 0 0x2000nand read 的命令格式是 nand read addr off | partition size ,总结起来就是读到哪去?从哪读?读多⼤?返回的结果是:NAND read: device 0 offset 0x0, size 0x2000file is nand_util.c,fun is nand_read_skip_bad,line is 599,NAND read from offset 2000 failed -740 bytes read: ERROR读失败,给出读失败错误码 -74要分析失败原因,先分析函数执⾏流程执⾏nand read 命令后,其实是执⾏了nand_read_skip_bad(nand, off, &size,(u_char *)addr);跳过坏块读函数的参数简单明了,从哪读,读到哪去,读多少,以及⼀个公共句柄(包含nand的信息,例如有多少个块,块⼤⼩等) 1int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,2 u_char *buffer)3 {4int rval;5 size_t left_to_read = *length;6 size_t len_incl_bad;7 u_char *p_buffer = buffer;89 len_incl_bad = get_len_incl_bad (nand, offset, *length); /* 函数分析见2017.11.14笔记(往下翻) */1011if ((offset + len_incl_bad) > nand->size) {12 printf ("Attempt to read outside the flash area\n");13return -EINVAL;14 }1516if (len_incl_bad == *length) {17 rval = nand_read (nand, offset, length, buffer);18if (!rval || rval == -EUCLEAN)19return0;20 printf ("NAND read from offset %llx failed %d\n",21 offset, rval);22return rval;23 }2425while (left_to_read > 0) {26 size_t block_offset = offset & (nand->erasesize - 1);27 size_t read_length;2829 WATCHDOG_RESET ();3031if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {32 printf ("Skipping bad block 0x%08llx\n",33 offset & ~(nand->erasesize - 1));34 offset += nand->erasesize - block_offset;35continue;36 }3738if (left_to_read < (nand->erasesize - block_offset))39 read_length = left_to_read;40else41 read_length = nand->erasesize - block_offset;42/* read_length 最⼤不会超过 nand->erasesize (128K) */43/* nand_read 函数是⼀个按块读函数 */44 rval = nand_read (nand, offset, &read_length, p_buffer);45if (rval && rval != -EUCLEAN) {46 printf ("NAND read from offset %llx failed %d\n",47 offset, rval);48 *length -= left_to_read;49return rval;50 }5152 left_to_read -= read_length;53 offset += read_length;54 p_buffer += read_length;55 }5657return0;58 }先看get_len_incl_bad1static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset,2const size_t length)3 {4 size_t len_incl_bad = 0;5 size_t len_excl_bad = 0;6 size_t block_len;78while (len_excl_bad < length) {9 block_len = nand->erasesize - (offset & (nand->erasesize - 1));1011if (!nand_block_isbad (nand, offset & ~(nand->erasesize - 1)))12 len_excl_bad += block_len;1314 len_incl_bad += block_len;15 offset += block_len;1617if (offset >= nand->size)18break;19 }2021return len_incl_bad;22 }想要看懂这个函数,先要理解offset的构成2017年11⽉14⽇10:00:40每天进步⼀点点nand->erasesize = 128K = 0x20000nand->erasesize - 1 = 0x1FFFFoffset & (nand->erasesize - 1) 保留低17位,清⾼位,因为nand的特性,所以是按块来统计长度block_len = nand->erasesize - offset & (nand->erasesize - 1) 作⽤是统计当前块要读的长度然后判断当前块是不是坏块,如果不是坏块,则让len_excl_bad += block_len,判断是否循环的标准是len_excl_bad < length 不论当前块是不是坏块,都让len_incl_bad += block_len,len_incl_bad 得到的是包含坏块的长度总结get_len_incl_bad函数的作⽤为:①如果偏移offset是从整块开始的,返回的结果是块的整数倍(不⽤看length,⽐如length是0x20001,则读两块)②如果偏移offset不是从整块开始的,返回的结果是块的整数倍+第⼀块要读的长度总之,返回的结果是按块补齐的再继续分析nand_read_skip_bad1if (len_incl_bad == *length) {2 rval = nand_read (nand, offset, length, buffer);3if (!rval || rval == -EUCLEAN)4return0;56return rval;7 }什么情况下,len_incl_bad == *length ?要读的内容⾥,没有坏块,且长度最后按块对齐(例如,从0x400开始读,读的长度为0x40000-0x400)如果不满⾜,则进⼊while循环读,在while⾥,按块读,先判断当前块是不是坏块,如果是则跳过,不是则读下⾯分析nand_read函数1/* 1.从哪读 2.读多少 3.读到哪去 */2static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,3 size_t *retlen, uint8_t *buf)4 {5struct nand_chip *chip = mtd->priv;6int ret;78/* Do not allow reads past end of device */9if ((from + len) > mtd->size)10return -EINVAL;11if (!len)12return0;13/* 选中芯⽚ */14 nand_get_device(chip, mtd, FL_READING);1516 chip->ops.len = len;17 chip->ops.datbuf = buf;18 chip->ops.oobbuf = NULL;1920 ret = nand_do_read_ops(mtd, from, &chip->ops);2122 *retlen = chip->ops.retlen;23/* 取消选中芯⽚ */24 nand_release_device(mtd);2526return ret;27 }其实真正的读函数是nand_do_read_ops,从哪去,读多少,读到哪去都被装载在chip->ops结构体中再看nand_do_read_ops函数1/**2 * nand_do_read_ops - [Internal] Read data with ECC3 *4 * @mtd: MTD device structure5 * @from: offset to read from6 * @ops: oob ops structure7 *8 * Internal function. Called with chip held.9*/10static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,11struct mtd_oob_ops *ops)12 {13int chipnr, page, realpage, col, bytes, aligned;14struct nand_chip *chip = mtd->priv;15struct mtd_ecc_stats stats;16int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;17int sndcmd = 1;18int ret = 0;19 uint32_t readlen = ops->len;//128K 0x20000 根据输⼊的长度决定20 uint32_t oobreadlen = ops->ooblen; // oobreadlen = 021 uint8_t *bufpoi, *oob, *buf;2223 stats = mtd->ecc_stats;2425 chipnr = (int)(from >> chip->chip_shift);26 chip->select_chip(mtd, chipnr);27/* realpage 总页地址(⾼17位) */28 realpage = (int)(from >> chip->page_shift);//pageshift is 1129 page = realpage & chip->pagemask;//pagemask = 1ffff30/* col 低11位 */31 col = (int)(from & (mtd->writesize - 1));//writesize = 2048, 2047 = 0x7ff32/* 得到页地址和列地址 */33 buf = ops->datbuf;34 oob = ops->oobbuf;3536while(1) {37 bytes = min(mtd->writesize - col, readlen); //128K 0x20000 根据输⼊的长度决定38 aligned = (bytes == mtd->writesize); //aligned = 1;3940/* Is the current page in the buffer ? */41if (realpage != chip->pagebuf || oob) {42 bufpoi = aligned ? buf : chip->buffers->databuf;43/* 对齐与不对齐读到的缓冲是不⼀样的 */44if (likely(sndcmd)) {45 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);46 sndcmd = 0;47 }4849/* Now read the page into the buffer */50if (unlikely(ops->mode == MTD_OOB_RAW))51 ret = chip->ecc.read_page_raw(mtd, chip,//nand_read_page_raw52 bufpoi, page);//从哪⾥读,读到哪⾥去,读多少53else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)54 ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);55/* nand_read_subpage */56else57 ret = chip->ecc.read_page(mtd, chip, bufpoi,//整页读 bufpoi = buf58 page); //nand_read_page_swecc59if (ret < 0)60break;6162/* Transfer not aligned data */63if (!aligned) {64if (!NAND_SUBPAGE_READ(chip) && !oob)65 chip->pagebuf = realpage;66 memcpy(buf, chip->buffers->databuf + col, bytes);67 }6869 buf += bytes;7071if (unlikely(oob)) {72/* Raw mode does data:oob:data:oob */73if (ops->mode != MTD_OOB_RAW) {74int toread = min(oobreadlen,75 chip->yout->oobavail);76if (toread) {77 oob = nand_transfer_oob(chip,78 oob, ops, toread);79 oobreadlen -= toread;80 }81 } else82 buf = nand_transfer_oob(chip,83 buf, ops, mtd->oobsize);84 }8586if (!(chip->options & NAND_NO_READRDY)) {87/*88 * Apply delay or wait for ready/busy pin. Do89 * this before the AUTOINCR check, so no90 * problems arise if a chip which does auto91 * increment is marked as NOAUTOINCR by the92 * board driver.93*/94if (!chip->dev_ready)95 udelay(chip->chip_delay);96else97 nand_wait_ready(mtd);98 }99 } else {100 memcpy(buf, chip->buffers->databuf + col, bytes);101 buf += bytes;102 }103104 readlen -= bytes;105106if (!readlen)107break;108109/* For subsequent reads align to page boundary. */110 col = 0;111/* Increment page address */112 realpage++;113114 page = realpage & chip->pagemask;115/* Check, if we cross a chip boundary */116if (!page) {117 chipnr++;118 chip->select_chip(mtd, -1);119 chip->select_chip(mtd, chipnr);120 }121122/* Check, if the chip supports auto page increment123 * or if we have hit a block boundary.124*/125if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))126 sndcmd = 1;127 }128129 ops->retlen = ops->len - (size_t) readlen;130if (oob)131 ops->oobretlen = ops->ooblen - oobreadlen;132133if (ret)134return ret;135136if (mtd->ecc_stats.failed - stats.failed)137return -EBADMSG;138139return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; 140 }。
nand_flash——调试总结
.size = MTDPART_SIZ_FULL,
.mask_flags = 0,
}
};
static struct nand_davinci_platform_data dm646x_nand_data = {
.name = "params",
.offset = MTDPART_OFS_APPEND,
.size = SZ_128K,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
/* kernel */
},
[1] = { /* Second memory resource is NAND I/O window */
.start = DAVINCI_DM646X_ASYNC_EMIF_DATA_CE2_BASE, /*必须根据硬件连线修改*/
(4)加载mtd分区
将第一步所填的flash分区信息加mtd分区里去。
insmod 完成后,使用命令ls /dev,就能看到nand flash的设备了。
第四步,文件系统 mount,可以使用jffs2,也可以使用yaffs文件系统,似乎yaffs mount的速度要快一些。
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_4M,
.mask_flags = 0,
},
/* file system */
{
.name = "filesystem",
u_boot移植(五)之分析uboot源码中nand flash操作
u_boot移植(五)之分析uboot源码中nand flash操作一、OneNand 和Nand Flash我们已经能从Nand Flash启动了,启动之后,大家会看到如下效果:可以看出,我们的uboot默认使用的是OneNand。
需要注意的是我们的FSC100上面是没有OneNand的,有的是K9F2G08U0B型号的NAND FLASH。
前面我们了解过Nor Flash 和Nand Flash,那OneNand Flash又是什么呢?二、uboot 源码中Nand Flash部分代码分析我们从Nand Flash初始化看起,打开lib_arm/board.c文件,为了紧抓主线,以下代码只列举出了主线代码。
可以看出,我们可以通过CONFIG_CMD_NAND和CONFIG_CMD_ONENAND两个宏来选择NAND FLASH初始化还是 ONENAND FLASH初始化。
uboot 中默认定义了宏CONFIG_CMD_ONENAND,所以选择的是ONENAND FLASH初始化。
我们的FSC100上面使用的是NAND FLASH,所以我们要定义CONFIG_CMD_NAND宏,取消CONFIG_CMD_ONENAND宏的定义。
嗯!先做个记录:修改include/configs/fsc100.h,定义宏CONFIG_CMD_NAND,取消宏CONFIG_CMD_ONENAND。
好了,接下我们看看nand_init()函数时如何实现的。
看以看出,这段代码调用根据CONFIG_SYS_MAX_NAND_DEVICE宏[默认没有定义]的值来决定系统中Nand Flash设备的个数。
接着调用nand_init_chip()函数完成Nand Flash初始化,然后计算出每块Nand Flash的大小。
最终会输出Nand Flash总的容量。
嗯!做个记录:修改include/configs/fsc100.h,定义宏CONFIG_SYS_MAX_NAND_DEVICE,值为1没有看明白的地方是给nand_init_chip()函数传递的参数,接下来我们来看看他们是如何定义的。
Nand-Flash存储器介绍及编程
Nand-Flash存储器1概述NOR和NAND是目前市场上两种主要的非易失闪存技术。
Nor-flash存储器的容量较小、写入速度较慢,但因其随机读取速度快,因此在嵌入式系统中,常应用在程序代码的存储中。
Nor-flash存储器的内部结构决定它不适合朝大容量发展;而NAND-flash存储器结构则能提供极高的单元密度,可以达到很大的存储容量,并且写入和擦除的速度也很快。
但NAND-flash存储器需要特殊的接口来操作,因此它的随机读取速度不及Nor-flash存储器。
二者以其各自的特点,在不同场合发挥着各自的作用。
NAND-flash存储器是flash存储器的一种技术规格,其内部采用非线性宏单元模式,为固态大容量存储器的实现提供了廉价有效的解决方案,因而现在得到了越来越广泛的应用。
例如体积小巧的U盘就是采用NAND-flash存储器的嵌入式产品。
由于NAND-flash(非线性flash)存储器内部结构不同于Nor-flash(线性flash)存储器,因此对它的读写操作也有较大的区别。
BF533中没有像支持SDRAM一样提供直接与NAND-flash存储器的接口,读写的过程要靠软件编程来完成。
本实验将以东芝公司的TC58DVM82A1FT芯片为例,介绍NAND-flash存储器芯片的读写流程和时序。
2 实验内容和目标包括以下几点。
2编写程序,读出器件的识别码(ID)。
3对NAND-flash的一个或若干个块进行擦除操作。
4在被擦除的一个或若干个块写入数据。
5将写入的数据读出并进行验证。
6查找坏块。
3NAND-flash介绍及编程指导NAND-flash存储器中的宏单元彼此相连,仅第一个和最后一个Cell分别与Work Line和BIT Line相连,因此NAND-flash架构的存储容量较Nor-flash架构的高。
NAND-flash存储器的容量较大,改写速度快,主要应用在大量资料的存储,如嵌入式产品中,包括数码相机、MP3随身听记忆卡等。
ARM9(S3C2440)之九nand flash的读写操作
九 ARM9(2440)对nand flash的读写操作转载自:骨Zi里德骄傲这篇文章转自别处,写的非常详细,让我们熟悉2440对nand flash 的整个操作过程:s3c2440对nandflash的操作(K9F2G08)nandflash在对大容量的数据存储中发挥着重要的作用。
相对于norflash,它具有一些优势,但它的一个劣势是很容易产生坏块,因此在使用nandflash时,往往要利用校验算法发现坏块并标注出来,以便以后不再使用该坏块。
nandflash 没有地址或数据总线,如果是8位nandflash,那么它只有8个IO口,这8个IO口用于传输命令、地址和数据。
nandflash主要以page(页)为单位进行读写,以block(块)为单位进行擦除。
每一页中又分为main区和spare区,main 区用于正常数据的存储,spare区用于存储一些附加信息,如块好坏的标记、块的逻辑地址、页内数据的ECC校验和等。
三星公司是最主要的nandflash供应商,因此在它所开发的各类处理器中,实现对nandflash的支持就不足为奇了。
s3c2440不仅具有nandflash的接口,而且还可以利用某些机制实现直接从nandflash启动并运行程序。
本文只介绍如何对nandflash实现读、写、擦除等基本操作,不涉及nandflash启动程序的问题。
在这里,我们使用的nandflash为K9F2G08U0A,它是8位的nandflash。
不同型号的nandflash的操作会有所不同,但硬件引脚基本相同,这给产品的开发扩展带来了便利。
因为不同型号的PCB板是一样的,只要更新一下软件就可以使用不同容量大小的nandflash。
K9F2G08U0A的一页为(2K+64)字节(加号前面的2K表示的是main区容量,加号后面的64表示的是spare区容量),它的一块为64页,而整个设备包括了2048个块。
这样算下来一共有2112M位容量,如果只算main区容量则有256M字节(即256M×8位)。
nandFlash编程内幕
(3)修改时钟源将/kernel/linux -2.6.32.2/arch/arm/mach -s3c2440/ 目录下的mach-smdk2440.c 文件改名为mach-mini2440.c。
因为mini2440 和mach-smdk2440.c 极其相似,以该文件为基础进行修改,在mach -mini2440.c 文件中将staticvoid__init smdk2440_map_io (void )函数中的晶振频率修改为mini2440 开发板上实际使用的12000000。
(4)为内核打上yaffs2 补丁①Yaffs2 文件系统是专门针对嵌入式设备,特别是使用Nand Flash 作为存储器的嵌入式设备而创建的一种文件系统,使用yaffs2 就可以支持大页的Nand Flash。
进入yaffs2 源代码目录执行如下命令:#./patch -ker.sh c /opt/FriendlyARM/mini2440/linux -2.6.32.2②配置内核以支持Yaffs2 文件系统在Linux 内核源代码根目录运行make xconfig,在“File systems ”选项中,找到“Miscellaneous filesystems ”菜单项,找到“YAFFS2 file system support ”并选中它,这样就在内核中添加了yaffs2 文件系统的支持,保存并退出。
然后在命令行中,执行make zImage 。
(5)修改Nand Flash 分区信息①在mach-mini2440.c 文件中添加Nand Flash 的分区信息,下面的代码将Nand Flash 分成了4 个分区,第1 分区也是BootLoader 所在的分区,对应dev/mtdblock0 ;第2 个分区是U-Boot 的参数分区,对应dev/mtdblock1 ;第 3 个分区是内核分区,对应dev/mtdblock2 ;第4 个分区为根文件系统分区对应dev/mtdblock3 。
NAND Flash图像记录系统底层写入控制技术
i tre v a m eo o NAND a h g o p o f l ep o a nela el dt f o i w t l f s r u st l t r g mmi g t . i a l, ec n r l r t a h wr emo e i h r n me F n l t o t l h e c i d i yh o e wi t
Ab t a t o e h n e t e wr e b n wi t f NAND a h i a e r c r i g s se sr c :T n a c h i a d d h o t l f s m g e o d n y t m,t e NAND a h o ・ hp wrt h l f s n c i i e tc n l g e fi tre v , n e la et ln n wo p a ea er s a c e n e h o o i so e l a e i t r v wo p a e a d t l r e e r h d a d i lme t dr s e t ey T e , e n e n mp e n e p c i l . h n a n w e v meh d b s d o t o a e n NAND a h o — h p i tre v it d o -h p 2 lv l i ei i g i r p s d wh c t ie e l f s n c i n e la e wr e a f c i e e p l n sp o o e , ih u i z s t n p n l h
内并行写入和 片内交叉 并行写入控制技术 ,在此基础上提 出了片 内交叉写入 和片外 2级流水线结合 的写入方 法, 该方法利用两组 NA ah片 内交叉写入的命令地 址和数据加载 时间来填补烧写 时间。 ND f s l 最后 用硬件方 式在 F GA P
NANDFLASH编程总结
NANDFLASH编程总结NAND闪存编程是指对NAND闪存芯片进行数据存储和擦除的过程。
NAND闪存是一种非易失性存储设备,被广泛应用于各种电子设备,如固态硬盘、闪存存储卡和移动设备等。
本文将对NAND闪存编程的一些基本概念、编程流程和注意事项进行总结。
一、NAND闪存基本概念NAND闪存由多个存储单元组成,每个存储单元可以存储一个或多个数据位。
存储单元分为页、块和平面。
每个页通常包含512个字节的数据和16个字节的校验。
一个块包含多个页,通常为64或128页。
一个平面包含多个块,通常为2048或4096块。
数据在NAND闪存中以块为单位进行擦除和编程操作。
二、NAND闪存编程流程1.擦除:首先,需要对整个块进行擦除操作,将块中的数据全部清除,以便写入新的数据。
擦除操作是一种高耗能、高时间延迟的操作,会导致NAND闪存寿命的损失,因此需要谨慎使用。
2.数据编程:一旦块被擦除,就可以开始数据编程。
数据编程是将数据写入已经擦除的块的过程。
编程操作通常在页的粒度进行,可以将数据以页为单位分成多次写入。
3.数据校验:在编程操作完成后,需要对已经编程的数据进行校验,以确保数据的正确性。
通常,每个页中的校验字节会存储之前数据的校验结果,编程操作后会重新计算并与之前的校验字节进行比较。
4.数据补齐:如果编程的数据不满一页,需要进行数据补齐操作,以保持页的对齐。
补齐操作可以在数据编程或校验之前进行。
5.坏块管理:在使用NAND闪存时,可能会遇到一些坏块,即无法正常擦除和编程的块。
在编程过程中需要进行坏块管理,即跳过这些坏块,避免对坏块进行擦除和编程操作。
三、NAND闪存编程注意事项1.写入范围限制:对于已经编程的页,不能对其进行覆盖写入。
如果需要修改已经编程的数据,需要先擦除整个块,再重新进行编程操作。
2.块擦除次数限制:每个块允许的擦除次数有限,超过允许次数后,块将被认定为坏块。
因此,在编程过程中应尽量避免多次擦除同一块。
MTD(3)-- nand flash的erase,read,write接口函数代码分析
本来是想按照代码流程往下讲bbt的,但是写着写着,还是要先介绍下mtd的几个基本flash读写擦函数接口。
那就调整下,先讲基本接口函数,再讲到bbt的时候,就不用回头来讲基本读写函数了,这样主线清楚些。
忽然觉得我讲的流程有些乱:)还没有讲flash的具体操作命令,要是穿插在下来的章节里面讲,会更乱,那就在这里补充下吧:)前面这章已经提到了一些东西,但我光顾着分解代码了,没有把他们关联起来。
我们知道,flash的基本操作就是erase、write、read。
那么kernel是如何执行这些操作的呢?首先我们要明确一点,CPU是通过flash控制器操作Flash芯片的,不同的芯片flash控制器不同,那么flash控制器有什么功能呢?硬件ECC校验,指令状态,工作时序等等;上面是flash的读写擦通用操作流程。
以上的代码都是针对某个特点平台的flash底层信息,比如我们就是针对TI的DM368来讲的,它们既要遵循一般的flash操作规范,如读写擦的命令字,也会有自己chip的一些特性,比如IO管脚复用,时序控制等等。
那么kernel如何管理种类繁多的flash设备?就是依赖MTD抽象层来实现的。
MTD定义了通用的flash操作接口,也针对大多数nand flash定义了通用的操作流程(nand_base.c),各种不同的chip只需要实现自己直接操作flash 设备的命令就好了。
info->chip.cmd_ctrl = nand_davinci_hwcontrol;info->chip.dev_ready = nand_davinci_dev_ready;info->chip.read_buf = nand_davinci_read_buf;info->chip.write_buf = nand_davinci_write_buf;dm368就是通过上面的几个接口函数来完成具体动作的。
13.6 NAND Flash控制器代码设计[共8页]
NAND Flash 控制器代码设计335.clkb(iClk), .dina(rFlash2RamDA),.dinb(iAhb2RamDB),.douta(rRam2FlashQA),.doutb(oRam2AhbQB),.ena(1'b0),.enb(1'b0),.wea(iFlash2RamWENA),.web(iAhb2RamWENB));13.6 NAND Flash 控制器代码设计NAND Flash 控制器的顶层模块由3个部分构成,分别为双端口RAM 控制器模块(mRamCtrl )、ECC 纠错码生成模块(mNandEccGeneration )和主控制器模块(NFController )。
其中,双端口RAM 控制器模块负责解析来自主控制器模块和其他主设备的控制信号,指导双端口RAM 进行读/写操作;ECC 纠错码生成模块用于生成ECC 纠错码,它在主控制器模块的控制下工作;主控制器模块是整个NAND Flash 控制器的核心,它接收来自CPU 等主设备的控制信号,将其转换成相应的NAND Flash 控制信号,执行读/写和擦除等基本操作,并协调mRamCtrl 和mNandEccGeneration 模块,使各模块形成一个统一整体。
NAND Flash 控制器的顶层代码如下。
top_fc (iClk,iRst,dio,CLE,ALE,CENeg,RENeg,WENeg,WPNeg,R,iOperate,iStart,oDone,iAddress0,iAddress1,oStatus,oFlashID,第13章综合实例3──NAND Flash 控制器设计336iCommand,iPageSize,iAhb2RamAddr,iAhb2RamOENB,iAhb2RamWENB,iAhb2RamDB,oRam2AhbQB,oEccCode,oEccResult);// 输入/输出信号声明input iClk;input iRst;/*********************************************** control signals to Nandflash***********************************************/ inout[7:0] dio;output CLE;output ALE;output CENeg;output RENeg;output WENeg;output WPNeg;input R;/********************************************* control signals from host to mFc*********************************************/ input[3:0] iOperate;input iStart;output oDone;input[31:0] iAddress0;input[31:0] iAddress1;input[31:0] iCommand;input[1:0] iPageSize;/********************************************control signals from host to RamCtrl*********************************************/ input[8:0] iAhb2RamAddr;input iAhb2RamOENB;。
u_boo移植(六)之支持Nand Flash操作
u_boo移植(六)之支持Nand Flash操作通过上一节uboot中Nand Flash操作的部分源码分析我们可以知道,如果想在uboot中驱动我们自己开发板上的Nand Flash设备,只需要完成以下几件事情就可以了。
1.修改include/configs/fsc100.h,定义宏CONFIG_CMD_NAND,取消宏CONFIG_CMD_ONENAND2.修改include/configs/fsc100.h,定义宏CONFIG_SYS_MAX_NAND_DEVICE,值为13.需要在drivers/mtd/nand目录下添加s5pc100_nand.c文件,完成FSC100的NAND Flash设备初始化(1)初始化Nand Flash硬件接线到SOC上的GPIO口(2)初始化SOC的Nand Flash控制器(3)实现s5pc100_hwcontrol函数中实现根据ctrl值是否含有NAND_CLE、NAND_ALE来决定是向NFCMD寄存器写值还是向NFADDR寄存器写值(4)实现s5pc00_select_chip函数,完成对Nand Flash设备片选和取消片选(5)实现s5pc100_dev_ready函数,完成对Nand Flash设备进行是否忙碌探测关于如何对Nand Flash进行读、写、擦除、坏块管理等操作,uboot源码中的MTD框架已经帮我们做好了。
好了,我们已经知道需要干什么了,接下来就开始干活吧!一、修改include/configs/fsc100.h文件,添加和取消相应的宏在fsc100.h文件里面,添加以下代码:二、drivers/mtd/nand目录下添加s5pc100_nand.c文件大家可以将此目录下的s3c2410_nand.c拷贝成s5pc100_nand.c,然后进行修改。
下面给出给我修改的代码:需要注意的是,不同的开发板配置不一样,流程都一样,说白了就是操作的寄存器不一样,大家可以根据自己开发板实际情况自行修改。
NANDFLASH芯片编程介绍
NANDFLASH芯片编程介绍1. 硬件特性:【Flash的硬件实现机制】Flash全名叫做Flash Memory,属于非易失性存储设备(Non-volatile Memory Device),与此相对应的是易失性存储设备(Volatile Memory Device)。
这类设备,除了Flash,还有其他比较常见的如硬盘,ROM等,与此相对的,易失性就是断电了,数据就丢失了,比如大家常用的内存,不论是以前的SDRAM,DDR SDRAM,还是现在的DDR2,DDR3等,都是断电后,数据就没了。
Flash的内部存储是MOSFET,里面有个悬浮门(Floating Gate),是真正存储数据的单元。
---------------------------------------------------------------------------------------------------金属-氧化层-半导体-场效晶体管,简称金氧半场效晶体管(Metal-Oxide-Semiconductor Field-Effect Transistor, MOSFET)是一种可以广泛使用在模拟电路与数字电路的场效晶体管(field-effect transistor)。
MOSFET依照其“通道”的极性不同,可分为n-type与p-type的MOSFET,通常又称为NMOSFET与PMOSFET,其他简称尚包括NMOS FET、PMOS FET、nMOSFET、pMOSFET等。
---------------------------------------------------------------------------------------------------在Flash之前,紫外线可擦除(uv-erasable)的EPROM,就已经采用用Floating Gate存储数据这一技术了。
图1.典型的Flash内存单元的物理结构数据在Flash内存单元中是的。