nor flash

NOR FLASH的讀取和RAM很類似,但不可以直接進行寫操作。對NOR FLASH的寫操作需要遵循特定的命令序列,最終由芯片內部的控制單元完成寫操作。從支持的最小訪問單元來看,NOR FLASH一般分爲 8 位的和16位的(當然,也有很多NOR FLASH芯片同時支持8位模式和是16 位模式,具體的工作模式通過特定的管腳進行選擇) 。 對8位的 NOR FLASH芯片,或是工作在8-BIT模式的芯片來說,一個地址對應一個BYTE(8-BIT)的數據。例如一塊8-BIT的NOR FLASH,假設容量爲4個 BYTE。那芯片應該有8個數據信號D7-D0 和2個地址信號,A1-A0。地址0x0對應第0個 BYTE,地址0x1對應於第1BYTE,地址0x2對應於第2個 BYTE,而地址0x3則對應於第3個BYTE. 對16位的 NOR FLASH芯片,或是工作在16-BIT模式的芯片來說,一個地址對應於一個16-BIT的數據。例如,一塊16-BIT的 NOR FLASH,假設其容量爲4個BYTE。那芯片應該有16 個數據信號線D15-D0 和1個地址信A0。地址 0x0對應於芯片內部的第0個16-BIT,地址0x1對應於芯片內部的第1個16-BIT。 FLASH一般都分爲很多個SECTOR,每個SECTOR包括一定數量的存儲單元。對有些大容量的FLASH,還分爲不同的BANK,每個BANK包括一定數目的SECTOR。FLASH的擦除操作一般都是以SECTOR,BANK或是整片FLASH爲單位的。在對FLASH進行寫操作的時候,每個BIT可以通過編程由1變爲0,但不可以有0修改爲1。爲了保證寫操作的正確性,在執行寫操作前,都要執行擦除操作。擦除操作會把FLASH的一個SECTOR,一個BANK或是整片FLASH 的值全修改爲0xFF。這樣,寫操作就可以正確完成了。
 ①.讀操作
  對norflash的讀操作比較簡單,系統上電後會自動進入讀模式,而且也不需要額外的命令來實現讀操作,下面的代碼就實現了
 NOR Flash的操作。  
  static unsigned int Read_SST1601(unsigned int addr)
  {
   return *((volatile unsigned int *)(addr));
  }
 ②.復位操作
  norflash不僅能夠實現硬件復位,而且可以實現軟件復位。軟件復位的操作是向任一地址寫入復位命令0xF0。下面的函數實現
 了軟件復位:
  static void Reset_SST1601(void)
  {
   *((volatile unsigned int *)0x0) = 0xf0;
  }
 ③.寫操作
  norflash的擦除操作和寫操作要稍微複雜一些,它們需要4個或6個週期來完成,每一個週期都要把相應的命令寫入norflash
 中的某一命令寄存器中。寫操作的過程爲第一個週期是把命令0xAA寫入地址爲0x5555的命令寄存器中,第二個週期是把命令0x55寫
 入地址爲0x2AAA命令寄存器中,第三個週期是把命令0xA0再寫入地址爲0x5555命令寄存器中,第四個週期爲真正地把要寫入的數據
 寫入到norflash的地址中。下面的函數實現了寫操作,其中該函數的兩個輸入參數分別爲要寫入的數據和地址,爲了方便,我們
 事先定義好命令寄存器.【注】參考芯片手冊
  #define    flash_base              0x00000000
  #define    CMD_ADDR0              *((volatile unsigned int *)(0x555<<1+flash_base))  
  #define    CMD_ADDR1              *((volatile unsigned int *)(0x2aa<<1+flash_base))
  static unsigned char SST1601_Program(unsigned int addr, unsigned int dat)
  {
   CMD_ADDR0 = 0xaa;
   CMD_ADDR1 = 0x55;
   CMD_ADDR0 = 0xa0;
   *((volatile unsigned int *)(addr)) = dat;
   return check_toggle();
  }
  static unsigned char check_toggle()
  {
   volatile unsigned int newtoggle,oldtoggle;
   oldtoggle = *((volatile unsigned int *)0x0); 
   while(1)
   {     
    newtoggle = *((volatile unsigned int *)0x0);           
    if((oldtoggle & 0x40)==(newtoggle & 0x40))
                     break;          
    if(newtoggle & 0x20)           //DQ5
    {
                     oldtoggle = *((volatile unsigned int *)0x0);
                     newtoggle = *((volatile unsigned int *)0x0);                
                     if((oldtoggle & 0x40)==(newtoggle & 0x40))
                            break;
                     else 
                            return 0;         //錯誤
    }     
    oldtoggle = newtoggle;
   }
   return 1;         //正確
  }
  check_toggle()的原理是連續兩次讀取數據總線上的數據,判斷數據總線上的第6位數值(DQ6)是否翻轉,如果沒有翻轉則正
 確,否則還要判斷第5位(DQ5),以確定是否是因爲超時而引起的翻轉。
 ④.擦除操作
  寫操作只能使“1”變爲“0”,而只有擦除才能使“0”變爲“1”。因此在寫之前一定要先擦除。擦除分爲塊擦除和整片擦除。塊擦除
 的過程爲第一個週期是把命令0xAA寫入地址爲0x5555的命令寄存器中,第二個週期是把命令0x55寫入地址爲0x2AAA命令寄存器中,
 第三個週期是把命令0x80再寫入地址爲0x5555命令寄存器中,第四個週期是把命令0xAA寫入地址爲0x5555的命令寄存器中,第五個
 週期是把命令0x55再寫入地址爲0x2AAA命令寄存器中,第六個週期是把命令0x30寫入要擦除塊的首地址內。下面的函數爲塊擦除,
 其中輸入參數爲要擦除塊的首地址.【注】參考芯片手冊
  unsigned char SST1601_sector_erase(unsigned int section_addr)
  {
   CMD_ADDR0 = 0xaa;
   CMD_ADDR1 = 0x55;
   CMD_ADDR0 = 0x80;
   CMD_ADDR0 = 0xaa;
   CMD_ADDR1 = 0x55;
   *((unsigned int *)(section_addr)) = 0x30;    
   return check_toggle();
  }
 ⑤.讀取芯片ID
  對norflash另一個比較常用的操作是讀取芯片的ID。讀取廠商ID的過程爲第一個週期是把命令0xAA寫入地址爲0x555的命令寄存器
 中,第二個週期是把命令0x55寫入地址爲0x2AA命令寄存器中,第三個週期是把命令0x90再寫入地址爲0x555命令寄存器中,第四個週期
 爲讀取地址爲0x100中的內容,即廠商ID(0x1C)。讀取設備ID的過程的前三個週期與讀取廠商ID相同,第四個週期是讀取地址爲0x01中
 的內容,即設備ID(0x2249)。下面的函數爲讀取芯片ID:
  unsigned int get_en29lv160ab_id(void)
  {
   U32 temp=0;
   CMD_ADDR0 = 0xaa;
   CMD_ADDR1 = 0x55;
   CMD_ADDR0 = 0x90;  
   temp = (*(volatile unsigned short *)(flash_base+ (0x100<<1)))<<16;
   temp |= (*(volatile unsigned short *)(flash_base + (1<<1));       
   return temp;
  }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章