⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 k9f1g08.c

📁 三星新一代2k page的k9f1g8u0a的底层驱动,已应用于工程之中.
💻 C
📖 第 1 页 / 共 2 页
字号:
        
        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 + -