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