?? norflash.c
字號:
#define __NORFLASH
#include "Norflash.h"
#undef __NORFLASH
//********************** Global Variable **********************
BYTE cFlashType; // flash類型
WORD wTotalSector; // 總共扇區數
DWORD wTotalSize; // Flash的總容量
//*************************************************************
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 讀當前NorFLASH類型.
//
// 返回: FLASH類型.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BYTE ReadNorFlashType (void)
{
// 用頭信息中的FLASH類型
cFlashType = NOR_FLASH_S29GL256N;
switch( cFlashType )
{
case NOR_FLASH_AM29LV320D:
wTotalSector = 64;
break;
case NOR_FLASH_AM29LV160D:
wTotalSector = 32;
break;
case NOR_FLASH_AM29LV800B:
wTotalSector = 16;
break;
case NOR_FLASH_S29GL256N:
wTotalSector = 256;
break;
default: // 錯誤
wTotalSector = 0;
return FALSE;
}
return cFlashType;
}//ReadNorFlashType()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 禁止Flash讀寫.
// 描述: 保護NorFlash, 讀寫都禁止. 禁止后讀數據只能讀到全0.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void DisableFlash (void)
{
Clr_MRST();
Clr_FLASHWP();
}//DisableFlash()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 允許Flash讀寫.
// 描述: 取消NorFlash保護, 允許對其讀寫.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void EnableFlash(void)
{
Set_MRST();
Set_FLASHWP();
}//EnableFlash()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 擦除單個扇區.
// 描述: 擦除NorFlash某個扇區. 耗時700-1500ms.
//
// [參數表]
// Dst: 扇區地址.
//
// 返回: 擦除操作是否成功. 0-失敗; 1-成功.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BYTE EraseOneSector(DWORD Dst)
{
int i,j;
ulong start, now, last;
vu_short *addr = (vu_short*)(0x00);
disable_interrupts(); // 關總中斷
EnableFlash(); // 允許Flash讀寫
addr[0x555] = (vu_short)0xAAAA;
addr[0x2AA] = (vu_short)0x5555;
addr[0x555] = (vu_short)0x8080;
addr[0x555] = (vu_short)0xAAAA;
addr[0x2AA] = (vu_short)0x5555;
addr = (vu_short*)(FLASH_ADDRESS+Dst);
addr[0] =(vu_short)0x3030;
for(i=0; i<300; i++) // 延時
for(j=0; j<1000; j++);
start = get_timer(0);
last = start;
addr = (vu_short*)(FLASH_ADDRESS+Dst);
while ((addr[0] & 0x8080) != 0x8080)
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT)
return FALSE;
// ----- 計算(顯示)等待時間, 單位:秒 -----
if ((now - last) > 100000)
{ /* every second */
last = now;
}
}
DisableFlash(); // 禁止Flash讀寫
addr = (vu_short *)(0x0);
addr[0] = (vu_short)0xF0F0;
return TRUE;
}//EraseOneSector()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 擦除扇區.
// 描述: 擦除給定扇區號的扇區內容.
//
// [參數表]
// wSector: 扇區號.
//
// 返回: 擦除操作是否成功. 0-失敗; 1-成功.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BYTE EraseSector(WORD wSector)
{
/* // Commnet: 舊彩顯板的寫法, 需要對Flash的前64K做特殊處理
// 注意: 每種類型的FLASH的前64K扇區是不同的!
DWORD wFirst64K[][9]={
{8,0x0000,0x2000,0x4000,0x6000,0x8000,0xA000,0xC000,0xE000}, //NOR_FLASH_AM29LV320D,8*8K
{4,0x0000,0x4000,0x6000,0x8000}, //NOR_FLASH_AM29LV160D,1*16K,2*8K,1*32K
{4,0x0000,0x4000,0x6000,0x8000}}; //NOR_FLASH_AM29LV800B,1*16K,2*8K,1*32K
WORD i;
int j;
if( wTotalSector == 0 || wSector>=wTotalSector ) //無效FLASH或參數錯誤
return FALSE;
if( wSector==0 ) // 對扇區0的特殊處理
{
for(i=0; i<wFirst64K[cFlashType-1][0]; i++)
{
if( EraseOneSector(wFirst64K[cFlashType-1][i+1]) == FALSE )
return FALSE;
for(j=0; j<300000; j++); // 延時等待
}
return TRUE;
}
else
return EraseOneSector((DWORD)wSector*65536);
*/
if( wTotalSector == 0 || wSector>=wTotalSector ) //無效FLASH或參數錯誤
return FALSE;
return EraseOneSector((DWORD)wSector*NOR_FLASH_SECTOR_SIZE); // 擦除指定的扇區
// 注: 新彩顯板的NorFlash每個扇區都是128KB.
}//EraseSector()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 寫一個字進Flash.
// 描述: 寫入一個字(4字節)到Flash的指定位置.
//
// [參數表]
// dest: 寫入地址.
// data: 寫入內容.
//
//返回: 0-完成; 1-寫入超時; 2-Flash未擦除.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static int write_word (ulong dest, ulong data)
{
vu_short *addr = (vu_short *)(FLASH_ADDRESS);
vu_short sdata;
ulong start;
/* Check if Flash is (sufficiently) erased */
if ((*((vu_long *)dest) & data) != data) {
return (2);
}
/* First write upper 16 bits */
sdata = (short)(data>>16);
sdata = (sdata >> 8) | (sdata << 8);
/* Disable interrupts which might cause a timeout here */
/* 在Writeflash中統一關、開中斷, 避免每次重復操作 */
// disable_interrupts();
addr[0x555] = 0xAAAA;
addr[0x2AA] = 0x5555;
addr[0x555] = 0xA0A0;
*((vu_short *)dest) = sdata;
/* re-enable interrupts if necessary */
//enable_interrupts();
/* data polling for D7 */
start = get_timer (0);
while ((*((vu_short *)dest) & 0x8080) != (sdata & 0x8080)) {
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
/* Now write lower 16 bits */
sdata = (short)(data&0xffff);
sdata = (sdata >> 8) | (sdata << 8);
/* Disable interrupts which might cause a timeout here */
// disable_interrupts();
addr[0x555] = 0xAAAA;
addr[0x2AA] = 0x5555;
addr[0x555] = 0xA0A0;
*((vu_short *)dest + 1) = sdata;
/* re-enable interrupts if necessary */
// enable_interrupts();
/* data polling for D7 */
start = get_timer (0);
while ((*((vu_short *)dest + 1) & 0x8080) != (sdata & 0x8080)) {
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
return (0);
}//write_word()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 寫Flash.
// 描述: 將數據塊寫入Flash.
//
// [參數表]
// src: 數據塊始地址.
// addr: Flash的寫入始地址.
// cnt: 寫入字符計數.
//
// 返回: 0-完成; 1-寫入超時; 2-Flash未擦除.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int Writeflash (uchar *src, ulong addr, ulong cnt)
{
ulong wp; // 寫入指針
ulong cp; // 拷貝指針. 用于處理始、末端非對齊數據
ulong data; // 臨時數據緩沖, 用于調整寫入的內容, 為寫入flash準備數據
//注: 因為write_word函數是以整型(4字節)進行寫入, 所以需要調整所需的格式.
int i, l, rc;
wp = (addr & ~3); /* get lower word aligned address */
disable_interrupts(); // 關閉總中斷, 防止因中斷引起的寫入超時
/* handle unaligned start bytes */
// 起始段數據(<4字節)處理, 目的是為批量寫入數據前對齊地址.
if ((l = addr - wp) != 0)
{
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) // 將flash中即將被寫入的位置的起始內容填充數據緩沖
{
data = (data << 8) | (*(uchar *)cp);
}
for (; i<4 && cnt>0; ++i) // 將起始段未對齊數據在數據緩沖中進行轉換
{
data = (data << 8) | *src++;
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) // 將數據緩沖的末端空余位置用flash中即將被寫入的位置的內容填充
{
data = (data << 8) | (*(uchar *)cp);
}
if ((rc = write_word( wp, data)) != 0) // 寫入
{
enable_interrupts(); // 打開總中斷
return (rc); // 寫入出錯返回
}
wp += 4; // 寫入指針指向下一位置
}
/* handle word aligned part */
// 批量寫入數據, 每次以一個字(32bit)的長度進行寫入
while (cnt >= 4)
{
data = 0;
for (i=0; i<4; ++i)
{
data = (data << 8) | *src++;
}
if ((rc = write_word( wp, data)) != 0) // 寫入
{
enable_interrupts(); // 打開總中斷
return (rc); // 寫入出錯返回
}
wp += 4; // 寫入指針指向下一位置
cnt -= 4;
}
if (cnt == 0) // 若上述操作正好寫完, 則返回完成.
{
enable_interrupts(); // 打開總中斷
return (0);
}
/* handle unaligned tail bytes */
// 處理數據塊的尾部數據(<4字節)
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) // 將尾部數據在數據緩沖中進行轉換
{
data = (data << 8) | *src++;
--cnt;
}
for (; i<4; ++i, ++cp) // 將數據緩沖的空余位置用flash中即將被寫入的位置的內容填充
{
data = (data << 8) | (*(uchar *)cp);
}
rc = write_word( wp, data);
enable_interrupts(); // 打開總中斷
return (rc); // 返回最終操作結果
}//Writeflash()
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -