nandflash的读写(2440)

时间:2023-02-13 19:55:31

说明:

根据物理结构上的区别 , NandFlash主要分为如下两类:
1)•SLC (Single Level Cell): 单层式存储
2)•MLC (Multi Level Cell): 多层式存储
@:SLC在存储格上只存一位数据, 而MLC则存放两位数据。

1.nand.c

#define NFCONF (*(volatile unsigned long*)0x4E000000)
#define NFCONT (*(volatile unsigned long*)0x4E000004)
#define NFCMD  (*(volatile unsigned char*)0x4E000008)
#define NFADDR (*(volatile unsigned char*)0x4E00000C)
#define NFDATA (*(volatile unsigned char*)0x4E000010)
#define NFSTAT (*(volatile unsigned char*)0x4E000020)

#define TACLS 1
#define TWRPH0 2
#define TWRPH1 1

void select_chip()
{
    NFCONT &= ~(1<<1);    
}

void deselect_chip()
{
    NFCONT |= (1<<1);    
}

void clear_RnB()
{
   NFSTAT |= (1<<2);
}

void send_cmd(unsigned cmd)
{
     NFCMD = cmd;
}

void send_addr(unsigned addr)
{
     NFADDR = addr;
}

void wait_RnB()
{
   while (!(NFSTAT&(1<<2)))    
   {
       ;    
   }
}

void nand_reset()
{
    //选中flash
    select_chip();
    
    //清除RnB
    clear_RnB();
    
    
    //发送0xff命令
    send_cmd(0xff);
    
    
    //等待RnB
    wait_RnB();
    
    
    //取消选中flash
    deselect_chip();
}

void nandflash_init()
{
    //初始化NFCONF
    NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
    
    //初始化NFCONT
    NFCONT = (1<<0) | (1<<1);
    
    //复位
    nand_reset();    
}

void NF_PageRead(unsigned long addr,unsigned char* buff)
{
    int i;
    
    //选中nandflash芯片
    select_chip();
    
    //清除RnB
    clear_RnB();
    
    //发送命令0x00
    send_cmd(0x00);
    
    //发送列地址
    send_addr(0x00);
    send_addr(0x00);
    
    //发送行地址
    send_addr(addr&0xff);
    send_addr((addr>>8)&0xff);
    send_addr((addr>>16)&0xff);
    
    //发送命令0x30
    send_cmd(0x30);
    
    //等待RnB
    wait_RnB();
    
    //读取数据
    for(i=0;i<2048;i++)
    {
       buff[i] = NFDATA;      
    }
    
    //取消选中nandflash芯片
    deselect_chip();
}

void nand_to_ram(unsigned long start_addr, unsigned char* sdram_addr, int size)
{
     int i;
     
    for( i=(start_addr >>11); size>0;)
    {
        NF_PageRead(i,sdram_addr);    
        size -= 2048;
        sdram_addr += 2048;
        i++;
    }
}

int NF_Erase(unsigned long addr)
{
    int ret;
    
  //选中flash芯片
    select_chip();
    
    //清除RnB
    clear_RnB();
    
    //发送命令0x60
    send_cmd(0x60);
    
    //发送行地址
    send_addr(addr&0xff);
    send_addr((addr>>8)&0xff);
    send_addr((addr>>16)&0xff);
    
    //发送命令D0
    send_cmd(0xD0);
    
    //等待RnB
    wait_RnB();
    
    //发送命令0x70
    send_cmd(0x70);
    
    //读取擦除结果
    ret = NFDATA;
    
    //取消选中flash芯片
    deselect_chip();
    
    return ret;
    
}

int NF_WritePage(unsigned long addr,unsigned char *buff)
{
    unsigned int i,ret = 0;
    //选中nandflash
    select_chip();
    
    //清除RnB
    clear_RnB();
    
    //发送0x80命令
    send_cmd(0x80);
    
    //发送2个列地址
    send_addr(0x00);
    send_addr(0x00);
    
    //发送3个行地址
    send_addr(addr&0xff);
    send_addr((addr>>8)&0xff);
    send_addr((addr>>16)&0xff);
    
    //发送数据
        for(i=0;i<2048;i++)
    {
       NFDATA = buff[i];      
    }
    
    //发送0x10命令
    send_cmd(0x10);
    
    //等待RnB
    wait_RnB();
    
    //发送0x70命令
    send_cmd(0x70);
    
    //读取写入结果
    ret = NFDATA;
    
    //关闭nandflash
    deselect_chip();
     return ret;
    
}

2.uart.c

#define GPHCON (*(volatile unsigned long*)0x56000070)
#define ULCON0 (*(volatile unsigned long*)0x50000000)
#define UCON0  (*(volatile unsigned long*)0x50000004)
#define UBRDIV0  (*(volatile unsigned long*)0x50000028)
#define UTRSTAT0 (*(volatile unsigned long*)0x50000010)
#define UTXH0 (*(volatile unsigned long*)0x50000020)
#define URXH0 (*(volatile unsigned long*)0x50000024)

#define PCLK 50000000
#define BAUD 115200

void uart_init()
{
    //1.配置引脚功能
    GPHCON &= ~(0xf<<4);
    GPHCON |= (0xa<<4);
    
    //2.1 设置数据格式
    ULCON0 = 0b11;
    
    //2.2 设置工作模式
    UCON0 = 0b0101;
    
    //3. 设置波特率    
    UBRDIV0 =(int)(PCLK/(BAUD*16)-1);
}

void putc(unsigned char ch)
{
    while (!(UTRSTAT0 & (1<<1)));
    UTXH0 = ch;  
}

unsigned char getc(void)
{
    unsigned char ret;

    while (!(UTRSTAT0 & (1<<0)));
    // 取数据
    ret = URXH0;  
    
    if ( (ret == 0x0d) || (ret == 0x0a) )
    {
        putc(0x0d);
        putc(0x0a);    
    }          
    else
        putc(ret);
        
        return ret;
}