部队网站建设招标,专门做推广的软文,iis能建设网站吗,门户网站有哪些局限性S3C2410处理器集成了8位NandFlash控制器。目前市场上常见的8位NandFlash有三星公司的k9f1208、k9f1g08、k9f2g08等。k9f1208、k9f1g08、k9f2g08的数据页大小分别为512Byte、2kByte、2kByte。它们在寻址方式上有一定差异#xff0c;所以程序代码并不通用。本文以S3C2410处理器和…S3C2410处理器集成了8位NandFlash控制器。目前市场上常见的8位NandFlash有三星公司的k9f1208、k9f1g08、k9f2g08等。k9f1208、k9f1g08、k9f2g08的数据页大小分别为512Byte、2kByte、2kByte。它们在寻址方式上有一定差异所以程序代码并不通用。本文以S3C2410处理器和k9f1208系统为例讲述NandFlash的读写方法。
NandFlash的数据是以bit 的方式保存在memory cell里的一般来说一个cell 中只能存储一个bit这些cell 以8 个或者16 个为单位连成bit line形成所谓的byte(x8)/word(x16)这就是NAND Device 的位宽。这些Line 组成Page page 再组织形成一个Block。k9f1208的相关数据如下
1block32page1page528byte512byte(Main Area)16byte(Spare Area)。
总容量为4096block数量*32page/block*512(byte/page)64Mbyte
NandFlash以页为单位读写数据而以块为单位擦除数据。按照k9f1208的组织方式可以分四类地址 Column Address、halfpage pointer、Page Address 、Block Address。A[0:25]表示数据在64M空间中的地址。
Column Address表示数据在半页中的地址大小范围0~255用A[0:7]表示
halfpage pointer表示半页在整页中的位置即在0~255空间还是在256~511空间用A[8]表示
Page Address表示页在块中的地址大小范围0~31用A[13:9]表示
Block Address表示块在flash中的位置大小范围0~4095A[25:14] 表示
把nand_flash想象成一本书每一页纸就是一页数据每一页书的宽就是flash的位宽长就是flash的列地址没几十页组成一个块所有的块又组成一本书就这样直观多了。
而页寄存器用来缓存一页数据。 #include linux/tmd/nand.h #define __REGb(x) (*(volatile unsigned char *)(x)) #define __REGw(x) (*(volatile unsigned short *)(x)) #define __REGi(x) (*(volatile unsigned int *)(x)) #define NF_BASE 0x4e000000 #if defined(CONFIG_S3C2440) #define NFCONF __REGi(NF_BASE 0x0) #define NFCONT __REGi(NF_BASE 0x4) #define NFCMD __REGb(NF_BASE 0x8) #define NFADDR __REGb(NF_BASE 0xc) #define NFDATA __REGb(NF_BASE 0x10) #define NFDATA16 __REGw(NF_BASE 0x10) #define NFSTAT __REGb(NF_BASE 0x20) #define NFSTAT_BUSY 1 #define nand_select() (NFCONT ~(1 1)) //cs低电平选中 #define nand_deselect() (NFCONT | (1 1)) #define nand_clear_RnB() (NFSTAT | (1 2)) #endif static inline void nand_wait(void) { int i; while(!(NFSTAT NFSTAT_BUSY)) for(i0; i10; i); } struct boot_nand_t { int page_size; int block_size; int bad_block_offset; }; static int is_bad_block(struct boot_nand_t *nand, unsigned long i) { unsigned char data; unsigned long page_num; nand_clear_RnB(); if(nand-page_size 512) { NFCMD NAND_CMD_READOOB; NFADDR nand-bad_block_offset 0xf; NFADDR (i 9) 0xff; NFADDR (i 17) 0xff; NFADDR (i 25) 0xff; }else if(nand-page_size 2048) { page_num i 11; /* addr / 2048 */ NFCMD NAND_CMD_READ0; NFADDR (nand-bad_block_offset ) 0xff; // Check FFh at the column address 2048 NFADDR (nand-bad_block_offset 8) 0xff; // of the 1st and 2nd page in the block NFADDR (page_num ) 0xff; // address of block NFADDR (page_num 8) 0xff; NFADDR (page_num 16) 0xff; NFCMD NAND_CMD_READSTART; }else { return -1; } nand_wait(); data (NFDATA 0xff); if(data ! 0xff) return 1; return 0; } static int nand_read_page_ll(struct boot_nand_t *nand, unsigned char *buf, unsigned long addr) { unsigned short *ptr16 (unsigned short *)buf; unsigned int i, page_num; nand_clear_RnB(); NFCMD NAND_CMD_READ0; if(nand-page_size 512){ NFADDR addr 0xff; NFADDR (addr 9)0xff; NFADDR (addr 17)0xff; NFADDR (addr 25)0xff; }else if (nand-page_size 2048){ page_num addr 11; NFADDR 0; //页内地址 为0时读取整页 NFADDR 0; NFADDR page_num 0Xff; //确定页地址 NFADDR (page_num 8) 0xff; NFADDR (page_num 16) 0xff; NFCMD NAND_CMD_READSTART; }else { return -1; } nand_wait(); //发送命令和地址后flash ready #if defined(CONFIG_S3C2410) for(i 0; i nand-page_size; i){ *buf (NFDATA 0xff); buf; } #elif defined(CONFIG_S3C2440) //循环读出数据 for(i 0; i (nand-page_size 1); i){ *ptr16 NFDATA16; ptr16; } #endif return nand-page_size; } static unsigned short nand_read_id() { unsigned short ret 0; NFCMD NAND_CMD_READID; NFADDR 0; res NFDATA; res (res 8) | NFDATA; return res; } extern unsigned int dynpart_size[]; int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) { int i, j; unsigned short nand_id; struct boot_nand_t nand; nand_select(); nand_clear_RnB(); for(i 0; i 10; i) ; nand_id nand_read_id(); if(nand_id 0xec76 || /* Samsung K91208 */ nand_id 0xad76) { /*Hynix HY27US08121A*/ nand.page_size 512; nand.block_size 16 * 1024; } else if(nand_id 0xecf1 ||/* Samsung K9F1G08U0B */ nand_id 0xecda ||/* Samsung K9F2G08U0B */ nand_id 0xecd3 ){/* Samsung K9K8G08 */ nand.page_size 2048; nand.block_size 128 * 1024; nand.bad_block_offset nand.page_size; }else{ return -1 ; //hang } if((start_addr (nand.block_size - 1)) || (size (nand.block_size - 1)))//检查块地址对齐即地址的低17为只能为0。 return -1; for(i start_addr; i (start_addr size);){ #ifdef CONFIG_S3C2410_NAND_SKIP_BAD if(i (nand.block_size - 1) 0){ //如果i时块地址对齐就执行不是块地址对齐就不检查 if(is_bad_block(nand, i) || is_bad_block(nand, inand.page_size)){//the 1st and 2nd page in the block i nand.block_size; size nand.block_size; continue; //跳回去检测下一个块是否为坏块 } } #endif j nand_read_page_ll(nand, buf, i); i j; buf j; } nand_deselect(); return 0; }