ARM裸机编程系列----nandflash
关于NAND FlashS5PV210的NAND Flash控制器有如下特点:
程序例子: /*nand.c*/ // NAND Flash初始化函数nand_init(),代码如下 void nand_init(void) { // 1. 配置NAND Flash NFCONF = (TACLS<<12)|(TWRPH0<<8)|(T WRPH1<<4)|(0<<3)|(0<<2)|(1<<1)|(0<<0); NFCONT =(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x3<<1)|(1<<0); // 2. 配置引脚 MP0_1CON = 0x22333322; MP0_2CON = 0x00002222; MP0_3CON = 0x22222222; // 3. 复位 nand_reset(); } 第一步 配置NAND Flash主要是设置NFCONF和NFCONT两个寄存器步骤:NFCONF寄存器 MODE = 1,使能NAND Flash控制器;? 第二步 配置引脚用于NAND Flash相关功能;第三步 复位复位函数nand_reset的相关代码如下:?static void nand_reset(void) { nand_select_chip(); nand_send_cmd(NAND_CMD_RES); nand_wait_idle(); nand_deselect_chip(); } NAND Flash的复位操作共4个步骤:1) 发片选,实质就是NFCONT &= ~(1<<1);往NFCONT的bit[1]写0;2) 发命令复位命令NAND_CMD_RES (0xff);实质就是NFCMMD = cmd;将命令写到NFCMMD寄存器;完整的NAND Flash命令信息见下图: 3) 等待NAND Flash 就绪;实质就是while( !(NFSTAT & (BUSY<<4)) ),读NFSTAT的bit[4]检查NAND Flash是否就绪; void nand_read_id(void) { nand_id_info nand_id; // 1. 发片选 nand_select_chip(); // 2. 读ID nand_send_cmd(NAND_CMD_READ_ID); nand_send_addr(0x00); nand_wait_idle(); nand_id.IDm = nand_read(); nand_id.IDd = nand_read(); nand_id.ID3rd = nand_read(); nand_id.ID4th = nand_read(); nand_id.ID5th = nand_read(); printf("NANDFlash: makercode = %x,devicec ode = %xrn",nand_id.IDm,nand_id.IDd); nand_deselect_chip(); } NAND Flash 读ID操作根据上图,NAND Flash的读ID操作共4个步骤: 第一步 发片选; 第二步 发读ID命令NAND_CMD_READ_ID(0x90); 第三步 发地址0x00;调用函数nand_send_addr(); 第四步 等待NAND Flash 就绪; 第五步 读ID;调用了nand_read()函数,实质就是读NFDATA寄存器; /*nand_send_addr()*/ { // 列地址,即页内地址 col = addr % NAND_PAGE_SIZE; // 行地址,即页地址 row = addr / NAND_PAGE_SIZE; // Column Address A0~A7 NFADDR = col & 0xff; for(i=0; i<10; i++); // Column Address A8~A11 NFADDR = (col >> 8) & 0x0f; for(i=0; i<10; i++); // Row Address A12~A19 NFADDR = row & 0xff; for(i=0; i<10; i++); // Row Address A20~A27 NFADDR = (row >> 8) & 0xff; for(i=0; i<10; i++); // Row Address A28~A30 NFADDR = (row >> 16) & 0xff; for(i=0; i<10; i++); } 首先根据页大小来获取页地址和页内偏移地址,然后通过5个周期将地址发送出去,实质就是写NFADDR寄存器,具体每个周期如何发送,查阅NAND Flash芯片手册可知,见下图: 发送地址后,就可以连续读出5个ID了,其中第一个是MAKDER CODE,第二个是DEVICE CODE。 NAND Flash擦除操作NAND Flash擦除函数nand_erase(),核心代码如下:nand_erase() { // 获得row地址,即页地址 unsigned long row = block_num * NAND_BLOCK_SIZE; // 1. 发出片选信号 nand_select_chip(); // 2. 擦除:第一个周期发命令0x60,第二个周期 发块地址,第三个周期发命令0xd0 nand_send_c md(NAND_CMD_BLOCK_ERASE_1st); for(i=0; i<10; i++); // Row Address A12~A19 NFADDR = row & 0xff; for(i=0; i<10; i++); // Row Address A20~A27 NFADDR = (row >> 8) & 0xff; for(i=0; i<10; i++); // Row Address A28~A30 NFADDR = (row >> 16) & 0xff; NFSTAT = (NFSTAT)|(1<<4); nand_send_cmd(NAND_CMD_BLOCK_ERASE_2st); for(i=0; i<10; i++); // 3. 等待就绪 nand_wait_idle(); // 4. 读状态 unsigned char status = read_nand_status(); } 根据上图,NAND Flash的擦除操作共6个步骤: NAND Flash 读操作<4> NAND Flash读函数copy_nand_to_sdram(),从NAND Flash中读数据到DRAM,核心代码如下:copy_nand_to_sdram() { // 1. 发出片选信号 nand_select_chip(); // 2. 从nand读数据到sdram,第一周期发命令0x00,第二周期发地址nand_addr,第三个周期发命令0x30,可读一页(2k)的数据 while(length) { nand_send_cmd(NAND_CMD_READ_1st); nand_send_addr(nand_addr); NFSTAT = (NFSTAT)|(1<<4); nand_send_cmd(NAND_CMD_READ_2st); nand_wait_idle(); // 列地址,即页内地址 unsigned long col = nand_addr % NAND_PAGE_SIZE; i = col; // 读一页数据,每次拷1byte,共拷2048次(2k),直到长度为length的数据拷贝完毕 for(; i<NAND_PAGE_SIZE && length!=0; i++,length--) { *sdram_addr = nand_read(); sdram_addr++; nand_addr++; } } // 3. 读状态 unsigned char status = read_nand_status(); } NAND Flash 读操作
NAND Flash写操作?NAND Flash写函数copy_sdram_to_nand (),从DRAM写数据到NAND Flash,核心代码如下:copy_sdram_to_nand () { // 1. 发出片选信号 nand_select_chip(); // 2. 从sdram读数据到nand,第一周期发命令0x80,第二周期发地址nand_addr,第三个周期写一页(2k)数据,第四周期发0x10 while(length) { nand_send_cmd(NAND_CMD_WRITE_PAGE_1st); nand_send_addr(nand_addr); // 列地址,即页内地址 unsigned long col = nand_addr % NAND_PAGE_SIZE; i = col; // 写一页数据,每次拷1byte,共拷2048次(2k),直到长度为length的数据拷贝完毕 for(; i<NAND_PAGE_SIZE && length!=0; i++,length--) { nand_write(*sdram_addr); sdram_addr++; nand_addr++; } NFSTAT = (NFSTAT)|(1<<4); nand_send_cmd(NAND_CMD_WRITE_PAGE_2st); nand_wait_idle(); } // 3. 读状态 unsigned char status = read_nand_status(); } 根据上图,NAND Flash的写操作共7个步骤: 完整代码地址:https://github.com/zhouhui321/gec210-nos/tree/master/nand (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |