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

📄 flash.c

📁 SPI接口的Data Flash at45db的C驱动
💻 C
字号:
//*------------------------------------------------------------------------------------------------
//* 文件名			   : flash.c
//* 功能描述		   : FLASH读写驱动
//* 作者    		   : 焦海波
//* 版本			   : 0.1
//* 建立日期、时间	   : 2008/05/04 16:04
//* 最近修改日期、时间 : 
//* 修改原因		   : 
//*------------------------------------------------------------------------------------------------
//*------------------------------------------ 头文件 ----------------------------------------------
#include	"/at91sam7x256/include/AT91SAM7X256.h"
#include	"/uCOS-II/ucos_ii.h"
#include	"spi.h"

#define	OS_GLOBALS 
#include	"flash.h"
//*---------------------------------------- 变量定义区 --------------------------------------------
static ST_SPI_DEV_RW stFlash;
//*================================================================================================
//*                     函 数 区
//*================================================================================================
//*------------------------------------------------------------------------------------------------
//* 函数名称 : FlashInitCfg
//* 功能描述 : 外部FLASH初始设置,实际完成与FLASH相连的SPI接口的初始设置工作
//* 入口参数 : 无
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
void FlashInitCfg(void)
{
	//* 复位FLASH
	AT91C_BASE_RSTC->RSTC_RMR = 0xA5000000 | (0x09 << 8);
	AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;

	//* 等待NRST引脚恢复为高电平
	while(!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL));

	//* 使能FLASH设备的片选线
	AT91C_BASE_PIOA->PIO_IDR = FLASH_NPCS;
	AT91C_BASE_PIOA->PIO_PPUDR = FLASH_NPCS;
	AT91C_BASE_PIOA->PIO_ASR = FLASH_NPCS;
	AT91C_BASE_PIOA->PIO_PDR = FLASH_NPCS;

	//* 设定为SPI模式0(CPOL:0,NCPHA:1),波特率为1MHz,片选有效之后延时12/MCK时间之后输出SPCK,
	//* 两个连续传输之间等待(32*1)/MCK时间
	FLASH_BASE->SPI_CSR[FLASH_NPCS_IDX] = AT91C_SPI_NCPHA | ((MCK/FLASH_RW_BAUD_RATE) << 8)| ((unsigned int)12 << 16) | ((unsigned int)1 << 24);
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __SendOptFlashCode
//* 功能描述 : 向FLASH发送操作码
//* 入口参数 :        <pbCmd>[in] 指向操作指令的指针
//*          :     <u8CmdLen>[in] 操作指令的长度
//*          :       <pbData>[in] 指向具体的操作数据的指针
//*          :   <u32DataLen>[in] 具体的操作数据的长度
//*          : <pfunCallBack>[in] 回调函数指针
//*          :        <pvArg>[in] 传递给回调函数的参数
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
static void __SendOptFlashCode(INT8U *pbCmd, INT8U u8CmdLen, INT8U *pbData, 
                               INT32U u32DataLen, PFUN_CALLBACK pfunCallBack, void *pvArg)
{
	memset(&stFlash, 0, sizeof(ST_SPI_DEV_RW));
	stFlash.u8SPIPort = SPI0;
	stFlash.u8NPCSPin = FLASH_NPCS_IDX;
	stFlash.pbCmd = pbCmd;
	stFlash.u8CmdLen = u8CmdLen;
	stFlash.pbData = pbData;
	stFlash.u32DataLen = u32DataLen;
	stFlash.pfunCallBack = pfunCallBack;
	stFlash.pvArg = pvArg;
	
	ReadAndWriteSPIDev(&stFlash);
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __GetFlashStatus
//* 功能描述 : 获得外部Flash状态
//* 入口参数 : 无
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
static INT8U __GetFlashStatus(void)
{
	INT8U __bCmd = FLASH_CMD_READ_STATUS;
	INT8U __bStatus = 0x00;
	
	__SendOptFlashCode(&__bCmd, 1, &__bStatus, 1, NULL, NULL);
	
	macWaitSPIRecvEnd();
	
	return __bStatus;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : CheckFlashID
//* 功能描述 : 外部FLASH初始设置,实际完成与FLASH相连的SPI接口的初始设置工作
//* 入口参数 : 无
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
void CheckFlashID(void)
{	
	while(FLASH_ID != (__GetFlashStatus() & FLASH_ID_MASK));
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : FlashRead
//* 功能描述 : 从指定页面的指定位置读取数据
//* 入口参数 :  <u16PageIdx>[in] 指定要读取的页面
//*          : <u16ByteAddr>[in] 指定数据在页面中的读取地址
//*          :      <pbData>[in] 指向接收缓冲区的指针
//*          :  <u32DataLen>[in] 要读取数据的长度
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
void FlashRead(INT16U u16PageIdx, INT16U u16ByteAddr, INT8U *pbData, INT32U u32DataLen)
{
	__align(4) INT8U __bCmd[8];
	U_FLASH_OPT_CODE __uFOptCode;
	INT8U __u8Err;

    memset(__bCmd, 0, sizeof(__bCmd));
    
    //* 按照严格的格式组装操作指令
    __uFOptCode.bstOptCode.bitByteAddr = u16ByteAddr;
    __uFOptCode.bstOptCode.bitPageAddr = u16PageIdx;
    __uFOptCode.bstOptCode.bitReserved = 0;
    __uFOptCode.bstOptCode.bitCmd = FLASH_CMD_CONTINUOUS_READ;
    *((unsigned int*)&__bCmd[0]) = macHighToLowSwitch(__uFOptCode.u32OptCode);
    
    OSMutexPend(hSPI0, 0, &__u8Err);
    {
    	__SendOptFlashCode(__bCmd, 8, pbData, u32DataLen, NULL, NULL);
    
	    macWaitSPIRecvEnd();
    }
    OSMutexPost(hSPI0);
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __IsErased
//* 功能描述 : 判断指定页面是否已经被擦除
//* 入口参数 : <u16PageIdx>[in] 指定要检查的页面号
//* 出口参数 : OS_TRUE - 已擦除
//*          : OS_FALSE - 未擦除或未擦除干净
//*------------------------------------------------------------------------------------------------
static BOOLEAN __IsErased(INT16U u16PageIdx)
{
	INT32U i;
	__align(4) INT8U __bFBuf[FLASH_BUF_SIZE];
	
	memset(__bFBuf, 0, sizeof(__bFBuf));
    
    FlashRead(u16PageIdx, 0, __bFBuf, sizeof(__bFBuf));
    
    for(i=0; i<FLASH_PAGE_SIZE/4; i++)
    {
    	if(((unsigned int*)__bFBuf)[i] != 0xFFFFFFFF)
    		return OS_FALSE;
    }
    
    return OS_TRUE;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __FlashErase
//* 功能描述 : 擦除指定页面
//* 入口参数 : <u16PageIdx>[in] 指定要擦除的页面
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
static BOOLEAN __FlashErase(INT16U u16PageIdx)
{
	INT8U i = 0;
	__align(4) INT8U __bCmd[4];	
	U_FLASH_OPT_CODE	__uFOptCode;
    
    while(i++ < 3)
    {
    	if(__IsErased(u16PageIdx))
    		return OS_TRUE;
    	else
    	{
    		memset(__bCmd, 0, sizeof(__bCmd));
    		
    		//* 按照严格的格式组装操作指令
		    __uFOptCode.bstOptCode.bitByteAddr = 0;
		    __uFOptCode.bstOptCode.bitPageAddr = u16PageIdx;
		    __uFOptCode.bstOptCode.bitReserved = 0;
		    __uFOptCode.bstOptCode.bitCmd = FLASH_CMD_PAGE_ERASE;
		    *((unsigned int*)&__bCmd[0]) = macHighToLowSwitch(__uFOptCode.u32OptCode);
    		__SendOptFlashCode(__bCmd, 4, NULL, 0, NULL, NULL);
            macWaitSPIRecvEnd();
            while(!(__GetFlashStatus() & FLASH_IS_RDY));
    	}
    }
    
    return OS_FALSE;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : FlashWrite
//* 功能描述 : 向指定页面的指定位置写入数据
//* 入口参数 :  <u16PageIdx>[in] 指定要擦除的页面
//*          : <u16ByteAddr>[in] 指定数据在页面中的写入地址
//*          :      <pbData>[in] 指向写入数据的指针
//*          :  <u16DataLen>[in] 写入数据的长度
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
BOOLEAN FlashWrite(INT16U u16PageIdx, INT16U u16ByteAddr, INT8U *pbData, INT16U u16DataLen)
{
	__align(4) INT8U __bCmd[4];	
	INT8U __bFBuf[FLASH_BUF_SIZE];
	U_FLASH_OPT_CODE __uFOptCode;
	INT16U	i;
	INT8U __u8Err;
	
	if(u16DataLen > FLASH_BUF_SIZE)
		return OS_FALSE;
		
	memcpy(__bFBuf, pbData, u16DataLen);

	
	//* 首先进行页面擦除
	if(!__FlashErase(u16PageIdx))
		return OS_FALSE;
	
	//* 向FLASH写入数据
	memset(__bCmd, 0, sizeof(__bCmd));
    		
    //* 按照严格的格式组装操作指令
	__uFOptCode.bstOptCode.bitByteAddr = u16ByteAddr;
	__uFOptCode.bstOptCode.bitPageAddr = u16PageIdx;
    __uFOptCode.bstOptCode.bitReserved = 0;
    __uFOptCode.bstOptCode.bitCmd = FLASH_CMD_PAGE_WRITE;
    *((unsigned int*)&__bCmd[0]) = macHighToLowSwitch(__uFOptCode.u32OptCode);
    
	OSMutexPend(hSPI0, 0, &__u8Err);
	{
		__SendOptFlashCode(__bCmd, 4, __bFBuf, u16DataLen, NULL, NULL);
	    macWaitSPIRecvEnd();
	    while(!(__GetFlashStatus() & FLASH_IS_RDY));
	}
	OSMutexPost(hSPI0);
    
    FlashRead(u16PageIdx, u16ByteAddr, __bFBuf, sizeof(__bFBuf));
    
    for(i=0; i<u16DataLen; i++)
    {
    	if(__bFBuf[i] != pbData[i])
    		return OS_FALSE;
    }
		
	return OS_TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -