LCD實驗學習筆記(七):NAND FLASH

s3c2440 CPU內置NAND FLASH控制器。相關寄存大器起始地址爲0x4e000000。函數

經過設置NFCONF寄存器,設置NAND FLASH 時序。spa

經過設置NFCONT寄存器,使能NAND FLASH、初始化ECC等。ip

代碼:cmd


 

#define GSTATUS1 (*(volatile unsigned int *)0x560000B0) //讀此寄存器能夠知道CPU芯片型號
#define BUSY 1flash

#define NAND_SECTOR_SIZE_LP 2048 //大頁每頁2048字節
#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1) //大頁掩碼???it

typedef unsigned int S3C24X0_REG32;select

//s3c2440 NAND FLASH相關寄存器
typedef struct {
  S3C24X0_REG32 NFCONF;
  S3C24X0_REG32 NFCONT;
  S3C24X0_REG32 NFCMD;
  S3C24X0_REG32 NFADDR;
  S3C24X0_REG32 NFDATA;
  S3C24X0_REG32 NFMECCD0;
  S3C24X0_REG32 NFMECCD1;
  S3C24X0_REG32 NFSECCD;
  S3C24X0_REG32 NFSTAT;
  S3C24X0_REG32 NFESTAT0;
  S3C24X0_REG32 NFESTAT1;
  S3C24X0_REG32 NFMECC0;
  S3C24X0_REG32 NFMECC1;
  S3C24X0_REG32 NFSECC;
  S3C24X0_REG32 NFSBLK;
  S3C24X0_REG32 NFEBLK;
} S3C2440_NAND;cpu

static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;//s3c2440 Nand flash 相關寄存器起始地址
數據

//供外部調用的函數聲明
void nand_init(void); //初始化
void nand_read(unsigned char *buf, unsigned long start_addr, int size);//讀取數據到緩衝區static

/* S3C2440的NAND Flash處理函數 */
static void s3c2440_nand_reset(void);
static void s3c2440_wait_idle(void);
static void s3c2440_nand_select_chip(void);
static void s3c2440_nand_deselect_chip(void);
static void s3c2440_write_cmd(int cmd);
static void s3c2440_write_addr_lp(unsigned int addr);
static unsigned char s3c2440_read_data(void);

//復位
static void s3c2440_nand_reset(void)
{
  s3c2440_nand_select_chip();//選片選
  s3c2440_write_cmd(0xff); //復位命令
  s3c2440_wait_idle(); //等待就緒
  s3c2440_nand_deselect_chip(); //取消片選
}

//等待就緒信號
static void s3c2440_wait_idle(void)
{
  int i;
  volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
  //最後一位爲1表示忙,忙就一直等
  while (!(*p & BUSY))
  for (i = 0; i < 10; i++);
}

//片選
static void s3c2440_nand_select_chip()
{
  s3c2440nand->NFCONT &= ~(1 << 1); //NFCONT寄存器[1]位Reg_nCE置0
  int i ;
  for (i = 0; i < 10; i++); //等待片選?
}


//取消片選
static void s3c2440_nand_deselect_chip()
{
  s3c2440nand->NFCONT |=(1<<1); //NFCONT寄存器[1]位Reg_nCE置1
}

//發送命令
static void s3c2440_write_cmd(int cmd)
{
  volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; //p指向NFCMD寄存器
  *p = cmd; //命令寫入命令寄存器
}

//發送地址
static void s3c2440_write_addr_lp(unsigned int addr)
{
  int i;
  volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
  int col, page;
  col = addr & NAND_BLOCK_MASK_LP; //獲得頁內地址。 每頁2K,頁內地址爲bit[0-10]
  page = addr / NAND_SECTOR_SIZE_LP; //獲得頁號。256M爲2的28次方,地址總位數爲27,即bit[11-27]爲頁號,共17位
  *p = col & 0xff; //地址後8位 ,A0-A7;
  for (i = 0; i < 10; i++);
  *p = (col >> 8) & 0x0f; //A8-A10
  for (i = 0; i < 10; i++);
  *p = page & 0xff; //頁號後後位 A11-A18
  for (i = 0; i < 10; i++);
  *p = (page >> 8) & 0xff;//A19-A26
  for (i = 0; i < 10; i++);
  *p = (page >> 16) & 0x1; //A27
  for (i = 0; i < 10; i++);}

//讀數據
static unsigned char s3c2440_read_data(void)
{
  volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
  return *p;
}


//初始化Nand Flash
void nand_init(void)
{
  //設置時序
  //這裏假設cpu頻率100MHz,即一個時鐘週期爲10ns
  #define TACLS 0
  #define TWRPH0 3 //nand flash手冊 twp最低要求12ns,即2個時鐘週期以上,因此這裏能夠取1的,3能夠保證400MHz時可用
  #define TWRPH1 0 //nand flash手冊 tCLH最低要求5ns,取值0要求CPU頻200Mhz如下
  s3c2440nand->NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4);
  //使能Nand Flash,禁止片選,初始化ECC
  s3c2440nand->NFCONT = (1 << 4) | (1 << 1) | (1 << 0);
  s3c2440_nand_reset(); //復位
}

//讀數據
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
  //Nand Flash的讀取單位最小是page,長度必須是page的整數倍。因此必須對齊
  if ((start_addr & NAND_BLOCK_MASK_LP)||(size & NAND_BLOCK_MASK_LP))
  {
    return;
  }
  s3c2440_nand_select_chip();//發出片選信號

  int i, j;
  for (i = start_addr; i < (start_addr+size);)
  {
    s3c2440_write_cmd(0); //發出READ0命令
    s3c2440_write_addr_lp(i);
    s3c2440_write_cmd(0x30);
    s3c2440_wait_idle();
    //讀取頁數據
    for ( j = 0; j <NAND_SECTOR_SIZE_LP;j++,i++)
    {
      *buf = s3c2440_read_data();
      buf++;
    }

  }

  s3c2440_nand_deselect_chip();//取消片選}

相關文章
相關標籤/搜索