📄 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 + -