Chinaunix首页 | 论坛 | 博客
  • 博客访问: 559237
  • 博文数量: 105
  • 博客积分: 3274
  • 博客等级: 中校
  • 技术积分: 1161
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-21 12:14
文章分类

全部博文(105)

文章存档

2011年(1)

2010年(104)

分类: 嵌入式

2010-05-08 11:47:13

/******************** (C) COPYRIGHT 2010-2015 launch ********************
* File Name          : k9f1g08.c
* Author             : zhanghonghu
* Version            : V1.0
* Date               : 05/01/2010
* Description        :
                    本文件提供k9f1g08的如下操作:
                    读取flash ID(探测flash)
                    flash 检错
                    读flash
                    写flash
                    擦除flash
                    flash空间管理
*******************************************************************************/
#include "global.h"
#include "string.h"
// flash function cmd
// read
#define FLASH_CMD_READ1         0x00
#define FLASH_CMD_READ2         0x30
//read for copy back
#define FLASH_CMD_READ_B1       0x00
#define FLASH_CMD_READ_B2       0x35
// read id
#define FLASH_CMD_READ_ID       0x90
// reset
#define FLASH_CMD_RESET         0xff
// page program
#define FLASH_CMD_PAGE_PRO1     0x80
#define FLASH_CMD_PAGE_PRO2     0x10
//cache program
#define FLASH_CMD_CACHE_PRO1    0x80
#define FLASH_CMD_CACHE_PRO2    0x15
// copy-back program
#define FLASH_CMD_COPY_B_PRO1   0x85
#define FLASH_CMD_COPY_B_PRO2   0x10
// block erase
#define FLASH_CMD_ERASE1        0x60
#define FLASH_CMD_ERASE2        0xd0
// random data input
#define FLASH_CMD_DATA_IN       0x85
// random data output
#define FLASH_CMD_DATA_OUT1     0x05
#define FLASH_CMD_DATA_OUT2     0xe0
// read status
#define FLASH_CMD_READ_STATUS   0x70
#define FLASH_BUSY              (1 << 6)      // 器件忙标志        
#define FLASH_OK                (1 << 0)      // 器件操作成功标志
typedef struct
{
    uint32 page_size;
    uint32 block_size;
    uint8 spare_size;
    uint8 bit_type;
    uint8 access_min;
}Flash_pro;
Flash_pro nand_type;
 

/*************************************************************************************************/
// 以下为硬件相关,移植到其他平台时需要更改
// start hw
// 引脚描述
/* LPC2119单片机的引脚    flash芯片的引脚
       P1.23                ClE  // 命令锁存使能端 高电平有效   作用于WE上升沿
       P1.22                ALE  // 地址锁存使能端 高电平有效   作用于WE上升沿
       P1.18                CE/  // 片选 低电平有效
       P1.20                WE/  // 写使能  低电平有效
       P1.21                RE/  // 读使能  在该口的下降沿把数据送到IO口                        
       P0.27                R/B  // 操作状态指示信号 低表示忙 高表示已经结束,准备好了
                            WP   // 写保护口 本例直接接高电平了,容易出问题
                            PRE  // 上电读使能,直接接高电平
P0.23-P0.16(8位端口)         D7-D0      
*/
#define   FLASH_CLE   (1<<23)  // p1.23
#define  FLASH_ALE   (1<<22)  // p1.22
#define  FLASH_CE      (1<<18)  // p1.18
#define  FLASH_WE      (1<<20)  // p1.20 
#define  FLASH_RE      (1<<21)  // p1.21
#define  FLASH_READY      (1<<27)  // p0.27
#define     FLASH_WP 
#define     SET_FLASH_ALE()      IO1SET = FLASH_ALE      //FALE   
#define     CLR_FLASH_ALE()      IO1CLR = FLASH_ALE   
#define     SET_FLASH_CLE()      IO1SET = FLASH_CLE      //FCLE   
#define     CLR_FLASH_CLE()      IO1CLR = FLASH_CLE   
#define     SET_FLASH_CE()       IO1SET = FLASH_CE       //FCE   
#define     CLR_FLASH_CE()       IO1CLR = FLASH_CE   
#define     SET_FLASH_WE()       IO1SET = FLASH_WE       //FWE   
#define     CLR_FLASH_WE()       IO1CLR = FLASH_WE   
#define     SET_FLASH_RE()       IO1SET = FLASH_RE       //FRE   
#define     CLR_FLASH_RE()       IO1CLR = FLASH_RE
#define     SET_FLASH_WP()         
#define     CLR_FLASH_WP()
#define     FLASH_READY_VALUE    ((IO0PIN >> 27)&0x00000001)
void nand_data_dir_out(void)
{
    IO0DIR |= 0x00ff0000;  
}
void nand_data_dir_in(void)
{
    IO0DIR &= 0xff00ffff;  
}
void nand_data_out( uint8 mIndex )
{
    IO0PIN = (IO0PIN & 0xff00ffff) | (mIndex << 16); 
}
uint8 nand_data_in(void)
{
    return ((uint8)(IO0PIN >> 16));
}
// end hw
/*************************************************************************************************/
static uint8 nand_busy_wait(void);
static void nand_write_cmd(uint8 cmd);
static void nand_write_add(uint16 column_add,uint16 row_add);
static uint8 nand_read_status(void);
static void nand_reset(void);
uint8 nand_work_ok(void);
uint32 nand_read_ID(void);
 

/*******************************************************************************
* Function Name  :
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void nand_init(void)
{
    uint32 id;
    // io
    IO1DIR |= FLASH_CLE | FLASH_ALE | FLASH_CE | FLASH_WE | FLASH_RE;  // 设置为输出
    IO0DIR = IO0DIR & (~FLASH_READY);  // 设置为输入   
 
    nand_data_dir_out();
   
    SET_FLASH_CE();
    SET_FLASH_WE();
    SET_FLASH_RE();
    CLR_FLASH_WP();
    CLR_FLASH_CLE();
    CLR_FLASH_ALE();
    // reset
    nand_reset();
    // test
    uart0_send_string("flash id is:");
    id = nand_read_ID();
    PrintHex(id>>24);
    PrintHex(id>>16);
    PrintHex(id>>8);
    PrintHex(id); 
    nand_valid_block_check();   
   
}
// 与平台无关系
/*******************************************************************************
* Function Name  :
* Description    : 忙等待
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_busy_wait(void)
{
    int i;
   
    while(0 == FLASH_READY_VALUE)
    {
        i++;      
        delay();
        if(i >= 60000)
        {         
            return 0;          
        }
    }
    return 1;
}
/*******************************************************************************
* Function Name  :
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void nand_write_cmd(uint8 cmd)
{
    CLR_FLASH_CE();           // 片选
    SET_FLASH_CLE(); 
 
    CLR_FLASH_WE(); 
    nand_data_out(cmd);
    SET_FLASH_WE(); 
    CLR_FLASH_CLE();
    SET_FLASH_CE(); 
   
}
/*******************************************************************************
* Function Name  : void nand_write_add(uint16 column_add,uint16 row_add)
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void nand_write_add(uint16 column_add,uint16 row_add)
{
    CLR_FLASH_CE();           // 片选
    SET_FLASH_WE();
    SET_FLASH_ALE();
   
    CLR_FLASH_WE();  
    nand_data_out((uint8)(column_add));
    SET_FLASH_WE();
 
    delay();
    CLR_FLASH_WE();   
    nand_data_out((uint8)((column_add >> 8) & 0x0f));
    SET_FLASH_WE();
    delay();
    CLR_FLASH_WE();   
    nand_data_out((uint8)(row_add));
    SET_FLASH_WE();
    delay();
    CLR_FLASH_WE();   
    nand_data_out((uint8)(row_add >> 8));
    SET_FLASH_WE();    
    delay();
    CLR_FLASH_ALE();
    SET_FLASH_CE();
}
/*******************************************************************************
* Function Name  :
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void nand_write_byte(uint8 bdata)
{
    SET_FLASH_WE();   
    CLR_FLASH_CE();
   
    CLR_FLASH_WE();
    delay();
    nand_data_out(bdata);
    delay();   
    SET_FLASH_WE();
   
    SET_FLASH_CE();
}
/*******************************************************************************
* Function Name  :
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_read_byte(void)
{
    uint8 data;
   
    nand_data_dir_in();
    SET_FLASH_WE();
    CLR_FLASH_CE();
   
    CLR_FLASH_RE();
  //  delay(); 
    nand_busy_wait();
    data = nand_data_in();
   
    SET_FLASH_CE();
    SET_FLASH_RE();
    nand_data_dir_out();
   
    return data;
}
/*******************************************************************************
* Function Name  :
* Description    :
* Input          : None
* Output         : None
* Return         : status
*******************************************************************************/
uint8 nand_read_status(void)
{  
    nand_write_cmd(FLASH_CMD_READ_STATUS);
    return (nand_read_byte());   
}
/*******************************************************************************
* Function Name  :
* Description    :
* Input          : None
* Output         : None
* Return         : status
*******************************************************************************/
void nand_reset(void)
{  
    nand_write_cmd(FLASH_CMD_RESET);
    nand_busy_wait();
}
/*******************************************************************************
* Function Name  :
* Description    : 检查flash是否OK
* Input          : None
* Output         : None
* Return         : 1 OK
*******************************************************************************/
uint8 nand_work_ok(void)
{
    uint8 status;  
      
    while(1)  
    {  
        status = nand_read_status();  
        if((status & FLASH_BUSY))
        {
            break;
        }
              
    }  
      
    status = nand_read_status();  
    if (!(status & FLASH_OK))
    {
        return 1;
    }         
    else
    {
        return 0;
    }
         
}
/*******************************************************************************
* Function Name  :
* Description    : 参考datasheet add为0
* Input          : None
* Output         : None
* Return         : flash id
                   1byte maker code
                   2byte device code
                   3byte don't care
                   4byte Page Size, Block Size, Spare Size, Organization,Serial access minimum
                   第4字节比较重要
*******************************************************************************/
uint32 nand_read_ID(void)
{
    uint32 id;
    uint8 data[4];
    id = 0;
   
    nand_write_cmd(FLASH_CMD_READ_ID);
    nand_write_add(0,0);
    data[0] = nand_read_byte();
    data[1] = nand_read_byte();
    data[2] = nand_read_byte();
    data[3] = nand_read_byte();
    if(0x00 == (data[3]&0x03))
    {
        nand_type.page_size = 1;
    }
    else if(0x01 == (data[3]&0x03))
    {
        nand_type.page_size = 2;
    }
    else
    {
       
    }
    if((data[3]&0x04))
    {
        nand_type.spare_size = 8;
    }
    else
    {
         nand_type.spare_size = 16;
    }
    if(0x00 == ((data[3] >> 4)&0x03))
    {
        nand_type.block_size = 64;
    }else if(0x01 == ((data[3] >> 4)&0x03))
    {
        nand_type.block_size = 128;
    }else if(0x02 == ((data[3] >> 4)&0x03))
    {
        nand_type.block_size = 256;
    }
    else
    {
       
    }
    if(data[3]&0x40)
    {
        nand_type.bit_type = 16;
    }
    else
    {
        nand_type.bit_type = 8;
    }
   
   
    id = (id << 8) + data[0];
    id = (id << 8) + data[1];
    id = (id << 8) + data[2];
    id = (id << 8) + data[3];
   
    return id;   

/*******************************************************************************
* Function Name  : uint8 nand_read_data(uint32 page_index,uint32 block_index,uint8 *buf)
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_read_data(uint32 page_index,uint32 block_index,uint8 *buf)
{
    uint16 column_add,row_add;
    uint16 block_cnt,page_cnt;   // 所处块数及第几页
    uint32 i;

    // 计算row_add地址
    block_cnt = block_index;
    page_cnt  = page_index;
    column_add = 0;
    row_add = (block_cnt << 6) | page_cnt;
    nand_write_cmd(FLASH_CMD_READ1);
    nand_write_add(column_add,row_add);
    nand_write_cmd(FLASH_CMD_READ2);
   
    nand_busy_wait();   
   
    nand_data_dir_in();
    CLR_FLASH_CE();
    for(i = 0; i < BYTES_PER_PAGE;i++)
    {  
        CLR_FLASH_RE();      
        delay();   // 必须加延时,否则数据会出现移位问题
        buf[i] = nand_data_in();       
        SET_FLASH_RE();    
    }
    SET_FLASH_CE();   
    nand_data_dir_out();
   
    return 1;
}
/*******************************************************************************
* Function Name  : uint8 nand_read_oob(uint32 page_index,uint32 block_index,uint8 *buf)
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_read_oob(uint32 page_index,uint32 block_index,uint8 *buf)
{
    uint16 column_add,row_add;
    uint16 block_cnt,page_cnt;   // 所处块数及第几页
    uint32 i;

    // 计算row_add地址
    block_cnt = page_index;
    page_cnt  = block_index;
    column_add = BYTES_PER_PAGE;
    row_add = (block_cnt << 6) | page_cnt;
    nand_write_cmd(FLASH_CMD_READ1);
    nand_write_add(column_add,row_add);
    nand_write_cmd(FLASH_CMD_READ2);
    nand_busy_wait();
   
    nand_data_dir_in();
 
    CLR_FLASH_CE();
    for(i = 0; i < BYTES_PER_PAGE_SPARE;i++)
    {  
        CLR_FLASH_RE();
        delay();
        buf[i] = nand_data_in(); 
        SET_FLASH_RE();
    }  
   
    SET_FLASH_CE();   
    nand_data_dir_out();
   
    return 1;
}
/*******************************************************************************
* Function Name  : uint8 nand_write_data(uint32 page_index,uint32 block_index,uint8 *buf)
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_write_data(uint32 page_index,uint32 block_index,uint8 *buf)
{
    uint16 column_add,row_add;
    uint16 block_cnt,page_cnt;   // 所处块数及第几页
    uint32 i;
    uint8 status;

    // 计算row_add地址
    block_cnt = page_index;
    page_cnt  = block_index;
    column_add = 0;
    row_add = (block_cnt << 6) | page_cnt;
    nand_write_cmd(FLASH_CMD_PAGE_PRO1);
    nand_write_add(column_add,row_add);
    nand_busy_wait();
   
    CLR_FLASH_CE();
   
    for(i = 0; i < BYTES_PER_PAGE_SPARE;i++)
    {
        CLR_FLASH_WE();  
        delay();
        nand_data_out(buf[i]);
        SET_FLASH_WE();
    }
   
    nand_write_cmd(FLASH_CMD_PAGE_PRO2);
   
 //   delay_ms(1);
    status = nand_work_ok();
   
    SET_FLASH_CE();    // 其实这个已经可以不要,为了统一格式
    return status;
}
/*******************************************************************************
* Function Name  : uint8 nand_write_oob(uint32 page_index,uint32 block_index,uint8 *buf)
* Description    : 编程附加数据,size不要超过64 每块的第0页和第1页的附加数据的第1个字节不要改动
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_write_oob(uint32 page_index,uint32 block_index,uint8 *buf)
{
    uint16 column_add,row_add;
    uint16 block_cnt,page_cnt;   // 所处块数及第几页
    uint32 i;
    uint8 status;

    // 计算row_add地址
    block_cnt = page_index;
    page_cnt  = block_index;
    column_add = BYTES_PER_PAGE;
    row_add = (block_cnt << 6) | page_cnt;
    nand_write_cmd(FLASH_CMD_PAGE_PRO1);
    nand_write_add(column_add,row_add);
    nand_busy_wait();
   
    CLR_FLASH_CE();
   
    for(i = 0; i < BYTES_PER_PAGE_SPARE;i++)
    {
        CLR_FLASH_WE();  
        delay();
        nand_data_out(buf[i]);
        SET_FLASH_WE();
    }
   
    nand_write_cmd(FLASH_CMD_PAGE_PRO2);
   
 //   delay_ms(1);
    status = nand_work_ok();
   
    SET_FLASH_CE();    // 其实这个已经可以不要,为了统一格式
    return status;
}

/*******************************************************************************
* Function Name  : uint8 nand_block_erase(uint32 block_index)
* Description    :
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8 nand_erase(uint32 block_index)
{
    uint16 row_add;
    uint8 status;
   
    // 计算row_add地址
    row_add = (block_index << 6) & 0xffc0;
    nand_write_cmd(FLASH_CMD_ERASE1);
    nand_write_add(0,row_add);
    nand_write_cmd(FLASH_CMD_ERASE2); 
    delay_ms(1);
    status = nand_work_ok();
    return status;
}
 
// 建立坏块表   
// K9F1G08U0A 共1024块, 出厂至少有1004块为好块, Block0 必为好块   
// Block0   : 存放坏块及坏块跳转表,   
//     page0: 存放坏块标志,1024字节对应1024块,坏块为0x00,好块为0xFF.   
//     page1: 存放跳转块的BlockIndex,每一个BlockIndex使用2字节表示,1024块占用2048字节   
//     other: Reserved   
// Blk1~960 : 保存数据   
// BlkN>960 : 程序先整片检查坏块,使用检查出来的Index大于960的好块为替换块.
/*******************************************************************************
* Function Name  :
* Description    : 检查指定块是否坏区,并标记
* Input          : None
* Output         : None
* Return         : 1有效 0无效
*******************************************************************************/
uint8 NandBlockCheck(uint32 block_index)
{
    uint8 buf[64];
   
    if(nand_read_oob(0,block_index,buf))
    {
       
        if(0xff == buf[0])
        {
            if(nand_read_oob(1, block_index, buf))
            {
                if(0xff == buf[0])
                {
                    return 1;
                }
                else
                {
                  //  uart0_send_string("the sec page data is:");
                   // PrintHex(buf[NF_ID_IVILID_NUM]);    
                   // uart0_send_string("\r\n");                 
                }
            }
        }
        else
        {
           // uart0_send_string("the first page data is:");
           // PrintHex(buf[NF_ID_IVILID_NUM]);    
          //  uart0_send_string("\r\n");          
        }
    }
 
    return 0;
}
   
/*******************************************************************************
* Function Name  :
* Description    : 检查flash坏区
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void nand_valid_block_check(void)
{
    uint16 i;
    for(i = 0; i < BLOCKS_PER_CHIP; i++)
    {      
        if(NandBlockCheck(i))
        {
       
        }
        /*
        else
        {
            uart0_send_string("Block ");
            PrintHex(i >> 8);
            PrintHex(i);
            uart0_send_string("is invalid\r\n");
        }
        */
    }
   
}
 
阅读(2950) | 评论(1) | 转发(0) |
0

上一篇:ch374简单驱动

下一篇:移植fat计划

给主人留下些什么吧!~~

chinaunix网友2010-10-26 11:15:18

楼主,高手,多多指教!