原创 K9F2808U0A存储结构与访问

2009-3-12 16:10 2156 1 1 分类: MCU/ 嵌入式

K<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />9F2808U0A的存储结构如图所示:<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /> 


点击开大图


                  1


K9F1208U0A的数据是以bit 的方式保存在cell,这些cell 8 个为单位连成column也是该器件的位宽,这些column528个为组组成Page.32page形成block(如图1)。而528column又被分为1st half2nd half3rd 三部分,其中1st half256column2nd half256column3rd   16column
正因为如此K9F2808U0A的地址分为三级:


--Block Address -- Page Address  --Column Address
Nand flash
以页为单位读写数据,而以块为单位擦除数据。地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。 


点击开大图
A[7:0]
就是所谓的column address


A8不参与抵制译码<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


A[13:9],用来确定page地址


A[23:14]用来确定block地址


地址传送顺序是Column Address,Page Address,Block Address
由于地址只能在I/O[7:0]上传递,因此,必须采用移位的方式进行。 例如,对于128MbitNAND flash,地址范围是0~0xFF_FFFF,只要是这个范围内的数值表示的地址都是有效的。


操作 1 步是传递column address,就是A[7:0],不需移位即可传递到I/O[7:0]上,而halfpage pointer bit8 是由操作指令决定的,即指令决定在哪个halfpage 上进行读写。第2 步就是将NAND_ADDR 右移9 位(因为bit8不参与地址译码),将A[13:9]传到I/O[7:0] 3 步将A[23:14]放到I/O .因此,整个地址传递过程需要3 步才能完成,即3-step addressing。对于存储空间大于128Mbitnandflash则需要四步完成,第四步传动地址为A[XX:24].我的板子引脚链接如图2和图3所示.


dd64984e-6a0c-4506-8e4c-ea5d52792edd.JPG


                    2


7b63ecad-d9ba-4a12-8661-daad568f2e19.JPG 



                      3


根据这个可以定义访问地址如下:


#define Nand_RB        (0x0400)


#define Nand_CE        (0x4000)


#define Nand_CLE     (0x04)


#define Nand_ALE     (0x08)


#define Nand_IO_DAT    (*(volatile unsigned char *)0x02000000)     


#define Nand_IO_CMD       (*(volatile unsigned char *)(0x02000000|Nand_CLE)) #define Nand_IO_ADR          (*(volatile unsigned char *)(0x02000000|Nand_ALE))


下面是程序的源码:


复位:


void Flash_Reset()      


{


    int i;


    NAND_CMD();


    Nand_IO_CMD = 0xff; 


    for (i=0;i<0x3ff;i++);     


}


ID


unsigned int Check_Flash_Id(void)


{


    int i;


    unsigned int id;


    NAND_CMD();


    Nand_IO_CMD = 0x90;


    NAND_INVALID();//这句不是必须的


    NAND_ADR();


    Nand_IO_ADR = 0;


    NAND_INVALID();


    NAND_DAT();


    for(i=0;i<10;i++);  


    id = Nand_IO_DAT<<8;//连续读出两个字节


    id += Nand_IO_DAT;


    NAND_INVALID();


    return id;


}


块擦除:


unsigned char Erase_Cluster(unsigned int block)


{


    unsigned int blockPage = (block<<5);


    int i;


 


    NAND_CMD();


    Nand_IO_CMD = 0x60;


    NAND_ADR();       


    Nand_IO_ADR = blockPage & 0xff; 


    Nand_IO_ADR = (blockPage>>8) & 0xff;


    for(i=0;i<2;i++);


    NAND_CMD();


    Nand_IO_CMD = 0xd0;   


    for(i=0;i<3;i++);   


    NAND_DAT();


    WAIT_RB();


    NAND_CMD();


    Nand_IO_CMD= 0x70;


    NAND_DAT();


    if (Nand_IO_DAT & 0x1)


    {


       NAND_INVALID();


       return 0;


    }


    else


    {


       NAND_INVALID();  


       return 1;


    }


}


页写int WritePage(unsigned int block,unsigned int page,unsigned char *buffer) 


{


    unsigned int blockPage = (block<<5) + page;


    int i;


    NAND_CMD();


    Nand_IO_CMD = 0x80;


    NAND_ADR();


    Nand_IO_ADR = 0;


    Nand_IO_ADR = blockPage & 0xff;


    Nand_IO_ADR = (blockPage>>8) & 0xff;


    NAND_DAT();


    for(i=0;i<528;i++)


    {


        Nand_IO_DAT=*buffer++;


    }       


    //WritePage(buffer);


    NAND_CMD();


    Nand_IO_CMD= 0x10;


    for(i=0;i<10;i++);


    WAIT_RB();      ////////////


    Nand_IO_CMD = 0x70; ///////////////////////////


    NAND_DAT();


    for(i=0;i<3;i++); 


    if((Nand_IO_DAT & 0x1)) 


    {


       NAND_INVALID();  


       return 0;


    }


    else


    {


       NAND_INVALID();


       return 1;     


    }


}


测试函数如下:


void Read_ID(void)


{


    unsigned short id;


    id = Check_Flash_Id();


    uart_printf("\nNandFLASH Chip's ID is 0x%4x\n",id);


}


 


void Erase_test(void)


{


    uart_printf("\nBegin to erase the last block...");


    if(Erase_Cluster(LASTBLOCK))


       uart_printf("\nOK! Compeleted.");


    else


        uart_printf("\nErase error!");


}


 


 


void Write_test(void)


{


    int i;


    unsigned char buffer[528];


    for(i=0;i<528;i++)


       buffer=0xaa;


    uart_printf("\nBegin to Write the first Page of the last block...");


    if(WritePage(LASTBLOCK,0,buffer))


        uart_printf("\nOK! Compeleted.");


    else


        uart_printf("\nWrite error!");


}


 


void Read_test(void)


{


    int i,j=0;


    unsigned char buffer[528];


   


    uart_printf("\nBegin to Read the first Page of the last block...");


    ReadPage(LASTBLOCK,0,buffer);


    for(i=0;i<528;i++)


    {


       if(buffer==0xaa)


           j++;


    }


    uart_printf("\n%4d Bytes verify match!",j);


}


:由于读写以页为单位,所以选定页后一次可以读写528个字节,但是不建议对第三块进行读写


 


 
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
1
关闭 站长推荐上一条 /1 下一条