S5PV210 NAND FLASH操作2(转载)
发布时间:2020-12-15 17:35:12 所属栏目:百科 来源:网络整理
导读:代码是S5PV210的NAND FLASH 源代码,没动。 #include "nand.h"#include "stdio.h"#define NFCONF ( *((volatile unsigned long *)0xB0E00000) )#define NFCONT ( *((volatile unsigned long *)0xB0E00004) )#define NFCMMD ( *((volatile unsigned long *)0x
代码是S5PV210的NAND FLASH 源代码,没动。 #include "nand.h" #include "stdio.h" #define NFCONF ( *((volatile unsigned long *)0xB0E00000) ) #define NFCONT ( *((volatile unsigned long *)0xB0E00004) ) #define NFCMMD ( *((volatile unsigned long *)0xB0E00008) ) #define NFADDR ( *((volatile unsigned long *)0xB0E0000C) ) #define NFDATA ( *((volatile unsigned long *)0xB0E00010) ) #define NFSTAT ( *((volatile unsigned long *)0xB0E00028) ) #define MP0_1CON ( *((volatile unsigned long *)0xE02002E0) ) #define MP0_2CON ( *((volatile unsigned long *)0xE0200300) ) #define MP0_3CON ( *((volatile unsigned long *)0xE0200320) ) #define MAX_NAND_BLOCK 8192 /*定义nand最大块数:8192块 */ #define NAND_PAGE_SIZE 2048 /*定义一页的容量:2048 byte */ #define NAND_BLOCK_SIZE 64 /*定义block大小:64页 */ #define TACLS 1 /* 时序相关的设置 */ #define TWRPH0 4 #define TWRPH1 1 #define NAND_CMD_READ_1st 0x00 /* 命令 */ #define NAND_CMD_READ_2st 0x30 #define NAND_CMD_RANDOM_WRITE 0x85 #define NAND_CMD_RANDOM_READ_1st 0x05 #define NAND_CMD_RANDOM_READ_2st 0xe0 #define NAND_CMD_READ_CB_1st 0x00 #define NAND_CMD_READ_CB_2st 0x35 #define NAND_CMD_READ_ID 0x90 #define NAND_CMD_RES 0xff #define NAND_CMD_WRITE_PAGE_1st 0x80 #define NAND_CMD_WRITE_PAGE_2st 0x10 #define NAND_CMD_BLOCK_ERASE_1st 0x60 #define NAND_CMD_BLOCK_ERASE_2st 0xd0 #define NAND_CMD_READ_STATUS 0x70 #define BUSY 1 #define ECC_EN (1<<4) #define CHIP_SELECTED (~(1<<1)) #define CHIP_DESELECTED (1<<1) #define CONTROL_EN (1<<0) static void nand_reset(void); static void nand_wait_idle(void); static void nand_select_chip(void); static void nand_deselect_chip(void); static void nand_send_cmd(unsigned long cmd); static void nand_send_addr(unsigned long addr); static unsigned char nand_read(void); static void nand_write(unsigned char data); typedef struct nand_id_info { //marker code unsigned char IDm; //device code unsigned char IDd; unsigned char ID3rd; unsigned char ID4th; unsigned char ID5th; }nand_id_info; // 复位 static void nand_reset(void) { nand_select_chip(); nand_send_cmd(NAND_CMD_RES); nand_wait_idle(); nand_deselect_chip(); } // 等待就绪 static void nand_wait_idle(void) { unsigned long i; while( !(NFSTAT & (BUSY<<4)) ) for(i=0; i<10; i++); } // 发片选 static void nand_select_chip(void) { unsigned long i; NFCONT &= ~(1<<1); for(i=0; i<10; i++); } // 取消片选 static void nand_deselect_chip(void) { NFCONT |= (1<<1); } // 发命令 static void nand_send_cmd(unsigned long cmd) { NFCMMD = cmd; } // 发地址 static void nand_send_addr(unsigned long addr) { unsigned long i; unsigned long col,row; // 列地址,即页内地址 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++); } // 读一个字节的数据 static unsigned char nand_read(void) { return NFDATA; } // 写一个字节的数据 static void nand_write(unsigned char data) { NFDATA = data; } // nandflash 初始化 void nand_init(void) { // 1. 配置nandflash NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<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(); } // 读芯片ID 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,devicecode = %xrn",nand_id.IDm,nand_id.IDd); nand_deselect_chip(); } // 擦除块 unsigned char nand_erase(unsigned long block_num) { unsigned long i = 0; // 获得row地址,即页地址 unsigned long row = block_num * NAND_BLOCK_SIZE; // 1. 发出片选信号 nand_select_chip(); // 2. 擦除:第一个周期发命令0x60,第二个周期发块地址,第三个周期发命令0xd0 nand_send_cmd(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(); if (status & 1 ) { // 取消片选信号 nand_deselect_chip(); printf("masking bad block %drn",block_num); return -1; } else { nand_deselect_chip(); return 0; } } // 从nand中读数据到sdram int copy_nand_to_sdram(unsigned char *sdram_addr,unsigned long nand_addr,unsigned long length) { unsigned long i = 0; // 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(); if (status & 1 ) { // 取消片选信号 nand_deselect_chip(); printf("copy nand to sdram failrn"); return -1; } else { nand_deselect_chip(); return 0; } } // 从sdram中写数据到nand int copy_sdram_to_nand(unsigned char *sdram_addr,unsigned long length) { unsigned long i = 0; // 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(); if (status & 1 ) { // 取消片选信号 nand_deselect_chip(); printf("copy sdram to nand failrn"); return -1; } else { nand_deselect_chip(); return 0; } } // 随机读数据 paddr页地址,offset页内偏移地址 unsigned char nand_random_read(unsigned long paddr,unsigned short offset) { unsigned char readdata; // 1. 发出片选信号 nand_select_chip(); // 2. 随机读页内某个地址的值 nand_send_cmd(NAND_CMD_READ_1st); //写入页地址 NFADDR = 0; NFADDR = 0; NFADDR = paddr&0xff; NFADDR = (paddr>>8)&0xff; NFADDR = (paddr>>16)&0xff; NFSTAT = (NFSTAT)|(1<<4); nand_send_cmd(NAND_CMD_READ_2st); nand_wait_idle(); nand_send_cmd(NAND_CMD_RANDOM_READ_1st); //写入页内偏移地址 NFADDR = offset&0xff; NFADDR = (offset>>8)&0xff; NFSTAT = (NFSTAT)|(1<<4); nand_send_cmd(NAND_CMD_RANDOM_READ_2st); readdata = nand_read(); // 3. 读状态 unsigned char status = read_nand_status(); if (status & 1 ) { // 取消片选信号 nand_deselect_chip(); printf("nand random read failrn"); return -1; } else { nand_deselect_chip(); return readdata; } } // 随机写数据 paddr页地址,offset页内偏移地址 unsigned char nand_random_write(unsigned long paddr,unsigned short offset,unsigned char wrdata) { // 1. 发出片选信号 nand_select_chip(); // 2. 随机写页内某个地址的值 nand_send_cmd(NAND_CMD_WRITE_PAGE_1st); NFADDR = 0; NFADDR = 0; NFADDR = paddr&0xff; NFADDR = (paddr>>8)&0xff; //NFADDR = (paddr>>16)&0xff; nand_send_cmd(NAND_CMD_RANDOM_WRITE); //写入页内偏移地址 NFADDR = offset&0xff; NFADDR = (offset>>8)&0xff; nand_write(wrdata); NFSTAT = (NFSTAT)|(1<<4); nand_send_cmd(NAND_CMD_WRITE_PAGE_2st); nand_wait_idle(); // 3. 读状态 unsigned char status = read_nand_status(); if (status & 1 ) { // 取消片选信号 nand_deselect_chip(); printf("nand random write failrn"); return -1; } else { nand_deselect_chip(); return 0; } } unsigned char read_nand_status(void) { unsigned char ch; int i; // 1. 发出片选信号 nand_select_chip(); // 2. 读状态 nand_send_cmd(NAND_CMD_READ_STATUS); for(i=0; i<10; i++); ch = nand_read(); // 3. 取消片选 nand_deselect_chip(); return ch; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |