📄 am29lv160drv.c
字号:
/**************************************************************************************************
*
* 作者: 胡翌博,浙江大学信电系电路与系统2001研
*
* 文件名:am29lv160Drv.c
*
* 版本: 1.1
*
* 功能描述:该文件提供了29lv160的驱动程序。
*
* 被本文件引用的文件列表:s3c4510bDef.h, typDef.h
*
* 应用本文件的文件列表:no
*
* 版本更迭:
* 日期 版本号 作者 备注
* 07-15-2003 1.0 胡翌博 --实验成功
* 07-27-2003 1.1 胡翌博 --s3c4510b.h更名为s3c4510bDef.h,修改相应的include语句
* --am29lv160.c更名为am29lv160Drv.c
**************************************************************************************************/
#include "s3c4510bDef.h"
#include "typDef.h"
#define AM_START_ADDR 0x1100000
#define AM_CHIP_HWORD_SIZE 0x100000 /*1M HWords*/
#define AM_ADDR_UNLOCK1 0x555
#define AM_ADDR_UNLOCK2 0x2aa
#define AM_DATA_UNLOCK1 0xaaaa
#define AM_DATA_UNLOCK2 0x5555
#define AM_SETUP_WRITE 0xa0a0
#define AM_SETUP_ERASE 0x8080
#define AM_CHIP_ERASE 0x1010
#define AM_SECTOR_ERASE 0x3030
/**************************************************************************************************
函数名称: amOpOverDetect()
函数功能: 采用poll方式检测flash擦写是否完成.
入口参数: ptr 数据写入地址/擦除扇区首址.
trueData 要写入的值.
timeCounter 超时计数.
返 回 值: OK 操作成功.
ERROR 操作失败.
备 注: 在预定时间内如果d7,d6仍不是truedata,则返回ERROR.
**************************************************************************************************/
STATUS amOpOverDetect(UINT16 *ptr, UINT16 trueData, int timeCounter)
{
int timeTmp = timeCounter;
volatile UINT16 *pFlash = ptr;
UINT16 buf1, buf2,curTrueData;
curTrueData = trueData & 0x8080; //先检测d7位.
while((*pFlash & 0x8080) != curTrueData)
{
if(timeTmp-- <= 0) break; //超时以后不是应该用return ERROR吗?
}
timeTmp = timeCounter;
buf1 = *pFlash & 0x4040; //(为保险)再检测d6位.
while(1)
{
buf2 = *pFlash & 0x4040;
if(buf1 == buf2) break;
else buf1 = buf2;
if(timeTmp-- <= 0)
{
return ERROR;
}
}
return OK;
}
/**************************************************************************************************
函数名称: sstWrite()
函数功能: 读取缓冲区数据,根据给定的长度写入指定地址.
入口参数: flashAddr 数据目标地址(flash).
buffer 数据源地址.
length 要写入的字节数.
返 回 值: NULL 写失败.
flashPtr flash的下一个地址.
备 注: 由于sst39vf160只能按半字(16bit)操作,所以
如果要多次调用这个函数来写入一个文件,则应
每次读取偶数个字节,以保证连续性.
**************************************************************************************************/
UINT16 *amWrite(UINT16 *flashAddr, UINT8 *buffer, int length)
{
int i, cLength;
volatile UINT16 *flashPtr;
volatile UINT16 *gBuffer;
flashPtr = flashAddr;
cLength = (length + 1)/2; //计算半字长度.
gBuffer = (UINT16 *)buffer;
while (cLength > 0)
{
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1; //解锁.
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_SETUP_WRITE;
*flashPtr = *gBuffer; //写入数据.
if(amOpOverDetect((UINT16 *)flashPtr, *gBuffer, 0x100000)) //检测写入是否成功.
{
//printf("warning: write flash may failed at:0x%x.\n", (int)flashPtr);
}
cLength--;
flashPtr++;
gBuffer++;
}
flashPtr = flashAddr;
gBuffer = (UINT16 *)buffer;
cLength = length/2;
for(i=0; i<cLength; i++) //写入的数据全部校验一次.
{
if(*flashPtr++ != *gBuffer++)
{
//printf("Error: write failed in SST39vf160 at 0x%x on verification.\n", (int)flashPtr);
return NULL;
}
}
if(length%2)
{
if((*flashPtr++ & 0x00ff) != (*gBuffer++ & 0x00ff)) /*奇数长度的最后一个字节.*/
{
//printf("Error: write failed in SST39vf160 at 0x%x on verification.\n", (int)flashPtr);
return NULL;
}
}
return (UINT16 *)flashPtr;
}
/**************************************************************************************************
函数名称: amChipErase()
函数功能: 擦除整个flash芯片.
入口参数: 无.
返 回 值: OK 擦除完全正确.
ERROR 有单元不能正确擦除.
备 注: datasheet上说典型时间为26s,实际大约15秒,
所以尽量用amSectorErase().
**************************************************************************************************/
STATUS amChipErase(void)
{
int i;
volatile UINT16 *flashPtr = NULL;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1; //连续解锁.
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_SETUP_ERASE;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_CHIP_ERASE; //写入擦除命令.
flashPtr = (volatile UINT16 *)AM_START_ADDR;
if(amOpOverDetect((UINT16 *)flashPtr, 0xffff, 0x800000) != OK)
{
//printf("warning: Chip Erase time out!\n");
}
flashPtr = (volatile UINT16 *)AM_START_ADDR;
for(i=0; i<AM_CHIP_HWORD_SIZE; i++,flashPtr++) //校验是否全为0xffff.
{
if(*flashPtr != 0xffff)
{
//printf("Debug: Erase failed at 0x%x in SST39VF160 on verification.\n", (int)flashPtr);
return ERROR;
}
}
return OK;
}
/**************************************************************************************************
函数名称: amSectorErase()
函数功能: 擦除指定的flash扇区.
入口参数: pSector 扇区地址.
返 回 值: OK 擦除完全正确.
ERROR 有单元不能正确擦除.
备 注:
**************************************************************************************************/
STATUS amSectorErase(UINT16 *pSector)
{
//int i;
volatile UINT16 *flashPtr = pSector;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1; //连续解锁.
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_SETUP_ERASE;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK1) = AM_DATA_UNLOCK1;
*((volatile UINT16 *)AM_START_ADDR + AM_ADDR_UNLOCK2) = AM_DATA_UNLOCK2;
*flashPtr = AM_SECTOR_ERASE; //写入擦除命令.
if(amOpOverDetect((UINT16 *)flashPtr, 0xffff, 0x20000) != OK)
{
return ERROR;
//printf("warning: Chip Erase time out!\n");
}
return OK;
}
/**************************************************************************************************
函数名称: amSecNumErase()
函数功能: 根据指定的扇区号(段号),擦除flash扇区.
入口参数: secNum 扇区号.
返 回 值: OK 该扇区擦除完全正确.
ERROR 该扇区有单元不能正确擦除.
备 注:
**************************************************************************************************/
STATUS amSecNumErase(int secNum)
{
int n;
STATUS rv;
n=secNum;
rv=OK;
switch(n)
{
case 0:
if(amSectorErase((UINT16 *)0x1100000) !=OK) //擦除第一个扇区.
{
rv=ERROR;
break;
}
rv=OK;
break;
case 1:
if(amSectorErase((UINT16 *)0x1102000) !=OK) //擦除第二个扇区.
{
rv=ERROR;
break;
}
rv=OK;
break;
case 2:
if(amSectorErase((UINT16 *)0x1103000) !=OK) //擦除第三个扇区.
{
rv=ERROR;
break;
}
rv=OK;
break;
case 3:
if(amSectorErase((UINT16 *)0x1104000) !=OK) //擦除第二个扇区.
{
rv=ERROR;
break;
}
rv=OK;
break;
case 4:
if(amSectorErase((UINT16 *)0x1108000) !=OK) //擦除第二个扇区.
{
rv=ERROR;
break;
}
rv=OK;
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
if(amSectorErase((UINT16 *)(17858560+32768*(n-4))) !=OK)
{
rv=ERROR;
break;
}
rv=OK;
break;
default: break;
}//end of switch(n)
return rv;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -