📄 k9f1g08.c
字号:
for(i=0; i<size; i++)
{
*DATA = Buf[i];
}
*CLE = K9F1G_PAGEPROGRAM2;
while(K9F1G_chkbusy(Chip)) ; // 可以去掉
return K9F1G08OK(Chip);
}
return FALSE;
}
// 块擦除, 返回FALSE为失败, 返回TRUE为成功
uint8 K9F1G_BlockErase(uint32 BlockIndex, uint8 Chip)
{
uint32 BlockAddr;
volatile uint8 *CLE;
volatile uint8 *ALE;
if(!Chip)
{
CLE = K9F1G08_CLE1;
ALE = K9F1G08_ALE1;
}
else
{
CLE = K9F1G08_CLE2;
ALE = K9F1G08_ALE2;
}
BlockAddr = BlockIndex<<(12+6);
*CLE = K9F1G_BLOCKERASE1;
*ALE = (BlockAddr>>12) & 0xFF;
*ALE = (BlockAddr>>20) & 0xFF;
*CLE = K9F1G_BLOCKERASE2;
while(K9F1G_chkbusy(Chip)) ; // 可以去掉
return K9F1G08OK(Chip);
}
// 读芯片ID
uint32 K9F1G_ReadID(uint8 Chip)
{
uint32 id1,id2,id3,id4;
volatile uint8 *CLE;
volatile uint8 *ALE;
volatile uint8 *DATA;
if(!Chip)
{
CLE = K9F1G08_CLE1;
ALE = K9F1G08_ALE1;
DATA = K9F1G08_DATA1;
}
else
{
CLE = K9F1G08_CLE2;
ALE = K9F1G08_ALE2;
DATA = K9F1G08_DATA2;
}
*CLE = K9F1G_READID;
*ALE = 0x00;
id1 = *DATA;
id2 = *DATA;
id3 = *DATA;
id4 = *DATA;
return (id1<<24|id2<<16|id3<<8|id4);
}
// 芯片内页拷贝, 包括附加数据, 返回FALSE表示失败, TRUE为成功
uint8 K9F1G_PageCopyBackProgram(uint32 SourcePageIndex, uint32 DestPageIndex, uint8 Chip)
{
//uint32 i;
uint32 PageAddr1,PageAddr2;
volatile uint8 *CLE;
volatile uint8 *ALE;
if(!Chip)
{
CLE = K9F1G08_CLE1;
ALE = K9F1G08_ALE1;
}
else
{
CLE = K9F1G08_CLE2;
ALE = K9F1G08_ALE2;
}
PageAddr1 = SourcePageIndex<<12;
*CLE = K9F1G_COPYBACKREAD1;
*ALE = (PageAddr1>>0) & 0xFF;
*ALE = (PageAddr1>>8) & 0x0F;
*ALE = (PageAddr1>>12) & 0xFF;
*ALE = (PageAddr1>>20) & 0xFF;
*CLE = K9F1G_COPYBACKREAD2;
//while(1)
//{
// if((K9F1G_ReadStatus(Chip) & K9F1G_BUSY) != 0)
// break;
//}
//for(i=0; i<10; i++) ;
while(K9F1G_chkbusy(Chip)) ; // 代替上面两种方法
PageAddr2 = DestPageIndex<<12;
*CLE = K9F1G_COPYBACKPROGRAM1;
*ALE = (PageAddr2>>0) & 0xFF;
*ALE = (PageAddr2>>8) & 0x0F;
*ALE = (PageAddr2>>12) & 0xFF;
*ALE = (PageAddr2>>20) & 0xFF;
*CLE = K9F1G_COPYBACKPROGRAM2;
while(K9F1G_chkbusy(Chip)) ; // 可以去掉
return K9F1G08OK(Chip);
}
// 可用块检测, 返回FALSE为坏块, TRUE为可用块
uint8 K9F1G_BlockCheck(uint32 BlockIndex, uint8 Chip)
{
//uint8 Buf[BYTESPERPAGESPARE];
uint8 Buf[1];
uint32 FirstPageIndex;
FirstPageIndex = BlockIndex<<6;
// 检查本块的第一页和第二页的附加区的第一个字节是否都为0xFF, 不是为坏块
if(K9F1G_PageSpareRead(Buf, 1, FirstPageIndex, Chip) == TRUE)
{
if(Buf[0] == 0xFF)
{
if(K9F1G_PageSpareRead(Buf, 1, FirstPageIndex+1, Chip) == TRUE)
{
if(Buf[0] == 0xFF)
return TRUE;
}
}
}
return FALSE;
}
// end of K9F1G08U0A basic operation
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// customer board operation
// 建立坏块表
// K9F1G08U0A 共1024块, 出厂至少有1004块为好块, Block0 必为好块
// Block0 : 存放坏块及坏块跳转表,
// page0: 存放坏块标志,1024字节对应1024块,坏块为0x00,好块为0xFF.
// page1: 存放跳转块的BlockIndex,每一个BlockIndex使用2字节表示,1024块占用2048字节
// other: Reserved
// Blk1~960 : 保存数据
// BlkN>960 : 程序先整片检查坏块,使用检查出来的Index大于960的好块为替换块.
#define FLASH1_BUSY BIT(2) // FLASH1 R/B P0.2 IN(Operate Busy)
#define FLASH2_BUSY BIT(4) // FLASH2 R/B P0.4 IN
#define FLASH1_WP BIT(3) // FLASH1 WP P0.3 OUT(Write Protect)
#define FLASH2_WP BIT(5) // FLASH2 WP P0.5 OUT
// 初始化控制状态管脚
void K9F1G_init(void)
{
PINSEL0 &= ~(FLASH1_BUSY|FLASH2_BUSY|FLASH1_WP|FLASH2_WP); // set as GPIO
// FLASH1 R/B P0.2 IN (0--IN,1--OUT)
// FLASH2 R/B P0.4 IN
// FLASH1 WP P0.3 OUT (0--Write Protect)
// FLASH2 WP P0.5 OUT
IO0DIR = (IO2DIR|FLASH1_WP|FLASH2_WP) & ~(FLASH1_BUSY|FLASH2_BUSY); // 0-in,1-out
IO0SET = FLASH1_WP|FLASH2_WP; // 0--Write Protect, 1--Write Enable
NOP;
//K9F1G_Reset(0);
//K9F1G_Reset(1);
//while(K9F1G_busy(0) || K9F1G_busy(1)) ;
}
// 锁定,禁止写入
void K9F1G_lock(uint8 Chip)
{
if(!Chip)
IO0CLR = FLASH1_WP; // P0.3 - FLASH1, 0-Protect, 1-Unprotect
else
IO0CLR = FLASH2_WP; // P0.5 - FLASH2, 0-Protect, 1-Unprotect
}
// 解锁,可以写入
void K9F1G_unlock(uint8 Chip)
{
if(!Chip)
IO0SET = FLASH1_WP; // P0.3 - FLASH1, 0-Protect, 1-Unprotect
else
IO0SET = FLASH2_WP; // P0.5 - FLASH2, 0-Protect, 1-Unprotect
}
// 检查busy线,0-空闲,1-busy
uint8 K9F1G_chkbusy(uint8 Chip)
{
uint8 temp;
// 从命令/数据到busy信号有效之间需要一定时间
NNOP(300); // >200 run in flash, 0 run in external ram
if(!Chip)
temp = !(IO0PIN>>2)&0x01; // P0.2 - FLASH1 Busy, 1-Ready, 0-Busy
else
temp = !(IO0PIN>>4)&0x01; // P0.4 - FLASH2 Busy, 1-Ready, 0-Busy
return temp;
}
// 检查并建立坏块表和块标志表
uint8 K9F1G_SetupBlockTable(uint8 Chip)
{
uint16 i,j;
memset(BlockStateTable[Chip],0x00,sizeof(BlockStateTable[Chip]));
memset(ValidBlockTable[Chip],0x00,sizeof(ValidBlockTable[Chip]));
for(i=0; i<BLOCKPERCHIP; i++) // BlockIndex
{
// 建立块标志列表
if(!K9F1G_BlockCheck(i,Chip)) // 坏块
BlockStateTable[Chip][i]=0x8000; // 最高位为1表示坏块,次高位表示占用情况
else
BlockStateTable[Chip][i]=0x0000; // 最高位为0表示好块
}
// 最高位为1表示坏块,次高位表示分配情况,再次高位表示占用情况
// 建立块替换列表
// 最后124块作为替换块,前900块作为可使用块,
// 可用块中的坏块以后124块中的没有使用的好块替换.
// 前900块中拿1块作为缓冲块(?).
for(i=0; i<MAX_VALIDBLOCK; i++)
{
if(BlockStateTable[Chip][i]>>14==0x0000) // 好块,空闲
{
ValidBlockTable[Chip][i]=i;
BlockStateTable[Chip][i]=0x0001<<15; // 标记好块占用
}
else // 坏块
{
for(j=MAX_VALIDBLOCK; j<BLOCKPERCHIP; j++)
{
if(BlockStateTable[Chip][j]>>14==0x00) // 好块,空闲
{
ValidBlockTable[Chip][i]=j;
BlockStateTable[Chip][j]=0x0001<<15; // 标记预备(替换)块是好块并占用
break;
}
}
if(j>=BLOCKPERCHIP) // 预备块用完
return FALSE;
}
}
return TRUE;
}
// 设置块写标志
void K9F1G_SetProgramBlkFlag(uint32 BlockIndex, uint8 Chip)
{
BlockStateTable[Chip][BlockIndex] |= 0x2000;
}
// 设置块擦除标志
void K9F1G_SetEraseBlkFlag(uint32 BlockIndex, uint8 Chip)
{
BlockStateTable[Chip][BlockIndex] &= 0xDFFF;
}
// 设置坏块标志
void K9F1G_SetBadBlkFlag(uint32 BlockIndex, uint8 Chip)
{
BlockStateTable[Chip][BlockIndex] |= 0x8000;
}
// 读块状态表
void K9F1G_ReadStatusTable(uint8 Chip)
{
K9F1G_PageRead((uint8*)BlockStateTable[Chip], BYTESPERPAGE, 1, Chip);
}
// 读可用块表
void K9F1G_ReadValidBlockTable(uint8 Chip)
{
K9F1G_PageRead((uint8*)BlockStateTable[Chip], BYTESPERPAGE, 0, Chip);
}
// 编程可用块表和块状态表
uint8 K9F1G_ProgramTable(uint8 Chip)
{
if(!K9F1G_BlockErase(0,Chip))
return FALSE;
if(K9F1G_PageProgram((uint8*)ValidBlockTable[Chip], BYTESPERPAGE, 0, Chip))
return FALSE;
if(K9F1G_PageProgram((uint8*)BlockStateTable[Chip], BYTESPERPAGE, 1, Chip))
return FALSE;
return TRUE;
}
// end of K9F1G08.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -