📄 drv_28f128.c
字号:
#include "vxWorks.h" /* always first */
#include "config.h" /* board support configuration header */
#include "typedef.h"
#include "../board/bsp.h"
/*#define BIT_0 0x01
#define BIT_1 0x02
#define BIT_2 0x04
#define BIT_3 0x08
#define BIT_4 0x10
#define BIT_5 0x20
#define BIT_6 0x40*/ // for pc-lint
#define BIT_7 0x80
/* Flash private command, only operate by 16 bit */
#define READ_FLASH_ARRAY 0xFFFF
#define READ_FLASH_ID_CODE 0x9090
#define CLEAR_FLASH_STATUS 0x5050
#define WRITE_FLASH_BUFFER 0xE8E8
#define ERASE_FLASH_BLOCK 0x2020
#define RESUME_FLASH_CMD 0xD0D0
#define READ_FLASH_STATUS 0x7070
#define SET_FLASH_LOCK_CMD1 0x6060
#define WRITE_FLASH_BYTE 0x4040
/*#define READ_FLASH_QUERY 0x9898
#define ERASE_FLASH_SUSPEND 0xB0B0
#define CONFIGURATION_FLASH 0xB8B8
#define SET_FLASH_LOCK_CMD2 0x0101
#define PROGRAM_FLASH_PROTECTION 0xC0C0*/ // for pc-lint
#define ESR_POLLING_TIMEOUT 0x00800000L
#define FLASH_BUFFER_SIZE 0x0F
/* Each block is 128K */
#define FLASH_BLOCK_MASK 0xFFFE0000
#define FLASH_NO_OPERATOR 0
#define FALSH_DIREC_WRITE 1
#define FALSH_ERASE_WRITE 2
#define DELAY_WRITE 0x01
#define DEFAULT_STATUS 0x00
_U8 Drv_FlashStatus = DEFAULT_STATUS;
_U32 WriteFlashSeg( _U16 *FlashAddr, _U32 ByteCount, _U8 *RamAddr );
_U16 ReadFlashStatus( _U16 *FlashAddr );
void WriteFlashStatus( _U16 *FlashAddr, _U16 value );
//static _U32 CheckFlashMem(_U32 pMem , _U32 pFlashBlock , _U32 Length , _U8 *retStatus, _U32 *StartOffset,_U32 *EndOffset);
_U32 FlashErase(_U16 *addr);
/* write flash buffer */
_U8 BlockMapMem[0x20000];
extern void BSP_PrintMemSimple(char *pData,_U32 Count);
/*****************************************************************************
function : write flash
return : SUCCESS if write success
FAILURE if write fail
******************************************************************************/
_U32 Drv_WriteFlash( _U32 FlashAddr, _U32 ByteCount, _U32 RamAddr )
{
_U32 AddrTemp, LenTmp = 0;
long WriteCount = 0;
_U8 *pSrc, *pDst, *pTmp;
/* Check input flash address */
if ( (FlashAddr < FLASH_START_ADDR)
||(FlashAddr > FLASH_END_ADDR))
{
Drv_Print("\r\n Input flash address error, FlashAddr = 0x%lx", FlashAddr);
return FAILURE;
}
/* Get flash address(in flash) */
pTmp = (_U8 *)FlashAddr;
/* Remained byte count that wait to write into flash */
WriteCount = (long)ByteCount;
/* Source address(in ram) */
pSrc = (_U8 *)RamAddr;
while (WriteCount > 0)
{
/* Get current writing flash block address */
AddrTemp = (_U32)pTmp & FLASH_BLOCK_MASK;
/* Read current block to BlockMapMem */
if (Drv_ReadFlash(AddrTemp, FLASH_BLOCK_SIZE, (_U32)(_U8*)BlockMapMem) != SUCCESS)
{
Drv_Print("\r\n ReadFlash error!");
return FAILURE;
}
/* Get writing ram address(in ram), offset from 0 to ByteCount */
pSrc = (_U8 *)(pSrc + LenTmp);
/* Get writing block address(in BlockMapMem), because AddrTemp in block,
so offset is (FlashAddr - AddrTemp), base is BlockMapMem. BlockMapMem
is map of flash */
pDst = (_U8 *)(FlashAddr - AddrTemp + BlockMapMem);
/* Get write count */
if ((_U32)WriteCount + FlashAddr - (FlashAddr & FLASH_BLOCK_MASK) >= FLASH_BLOCK_SIZE)
{
LenTmp = AddrTemp + FLASH_BLOCK_SIZE - FlashAddr;
}
else
{
/* If last block, only write remain content */
LenTmp = (_U32)WriteCount;
}
/* If content is same in a block, no erase no write */
if (memcmp(pDst, pSrc, LenTmp) != 0)
{
if (DELAY_WRITE == Drv_FlashStatus)
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
memcpy((char *)pDst, (char *)pSrc, LenTmp);
if (FlashErase((_U16 *)AddrTemp) == FAILURE)
{
Drv_Print("\r\n Erase error!");
return FAILURE;
}
if (FAILURE == WriteFlashSeg((_U16 *)AddrTemp, FLASH_BLOCK_SIZE, BlockMapMem))
{
Drv_Print("Write Flash Seg fail.");
return FAILURE;
}
}
if (DELAY_WRITE == Drv_FlashStatus)
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
pTmp = (_U8 *)(AddrTemp + FLASH_BLOCK_SIZE);
WriteCount -= (long)LenTmp;
FlashAddr += LenTmp;
}
return SUCCESS;
}
/*****************************************************************************
function : Read data from flash memory chip.
return : void
******************************************************************************/
_U32 Drv_ReadFlash( _U32 FlashAddr, _U32 ByteNum, _U32 RamAddr )
{
_U32 loop ;
_U8 *src ;
_U8 *dest ;
if ( (FlashAddr < FLASH_START_ADDR)
||(FlashAddr >= FLASH_END_ADDR) )
{
Drv_Print("\r\n Read flash address error, FlashAddr = 0x%lx", FlashAddr);
return FAILURE;
}
if (RamAddr == 0)
{
return FAILURE;
}
src = (_U8 *)FlashAddr ;
dest = (_U8 *)RamAddr ;
/* Write status word */
WriteFlashStatus((_U16 * )FLASH_START_ADDR, CLEAR_FLASH_STATUS);
WriteFlashStatus((_U16 * )FLASH_START_ADDR, READ_FLASH_ARRAY);
/* Get data from flash */
for (loop = 0; loop < ByteNum; loop++)
{
*dest++ = *src++;
}
return SUCCESS;
}
/****************************************************************************
function : Judge flash if on board by read manuf code and device code,
in 28f640 is 0x89 and 0x17, in 28f128 is 0x89 and 0x18
return : FLASH_28F640 or FLASH_28F128 if on board
FAILURE if no flash
****************************************************************************/
_U32 Drv_IsFlashOnboard(void)
{
_U16 ucManufCode, ucDeviceCode;
*((_U16 * )FLASH_START_ADDR) = READ_FLASH_ID_CODE;
ucManufCode = *((_U16 *) FLASH_START_ADDR );
/* 在读取identifier codes时,A0地址是无效的,最低位从A1开始。文档4.2 */
ucDeviceCode = *((_U16 *) (FLASH_START_ADDR + 2));
if ( (ucManufCode != 0x89)
||((ucDeviceCode != 0x17)&&(ucDeviceCode != 0x18)) )
{
Drv_Print("\r\n Flash is not on board, Manuf Code is 0x%x, Device code is 0x%x",
ucManufCode, ucDeviceCode);
return FAILURE;
}
/* Switch status to read */
WriteFlashStatus((_U16 * )FLASH_START_ADDR, CLEAR_FLASH_STATUS);
WriteFlashStatus((_U16 * )FLASH_START_ADDR, READ_FLASH_ARRAY);
return ucDeviceCode;
}
#if USE_FLASH_BUFFER
/*****************************************************************************
function : write flash one block
return : SUCCESS if write success
FAILURE if write fail
******************************************************************************/
_U32 WriteFlashSeg( _U16 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
_U32 i,j,t = 0;
_U16 *p1, *p2, status;
_U32 BufCount, LastCount, Length = FLASH_BUFFER_SIZE;
/* Switch to read array status */
WriteFlashStatus( (_U16 *)FlashAddr, CLEAR_FLASH_STATUS ) ;
WriteFlashStatus( (_U16 *)FlashAddr, READ_FLASH_ARRAY ) ;
p1 = (_U16 *)FlashAddr;
p2 = (_U16 *)RamAddr;
/* Buffer count that wait for writing, one buffer length is 16 word(32 byte) */
BufCount = ByteCount/((FLASH_BUFFER_SIZE + 1)*2) ;
/* Last buffer data length */
LastCount = (_U32)(ByteCount%((FLASH_BUFFER_SIZE + 1)*2));
if (DELAY_WRITE == Drv_FlashStatus)
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
for(i = 0; i <= BufCount; i++)
{
Length = FLASH_BUFFER_SIZE;
/* Deal with last buffer */
if(i == BufCount)
{
if(LastCount != 0)
Length = LastCount - 1;
else
break;
}
/* 1、Write status */
WriteFlashStatus((_U16 *)p1, WRITE_FLASH_BUFFER);
status = ReadFlashStatus(p1);
while( ((status & BIT_7) != BIT_7)
&& (t++ <= ESR_POLLING_TIMEOUT) )
{
/*如果写入有些问题可以考虑在此加入写状态字命令 :
WriteFlashStatus((_U16 *)p1, WRITE_FLASH_BUFFER);
*/
status = ReadFlashStatus(p1);
}
if (t >= ESR_POLLING_TIMEOUT)
{
// Drv_Print("\r\n Read Flash Status Timeout!!!,%d",__LINE__);
return FAILURE;
}
// Drv_Print("\r\n ReadFlash OK! %d",__LINE__);
/* 2、Write length */
WriteFlashStatus((_U16 *)p1, (_U16)Length);
// Drv_Print("\r\n %d Write Status Addr: 0x%x, Write Value:0x%x",__LINE__,(_U32)p1,Length);
/* 3、Write data */
for (j = 0; j <= Length; j++)
{
WriteFlashStatus((_U16 *)p1++, *(_U16 *)p2++);
}
/* 减8是为了保证地址在FLASH的范围内,因为前面有P1++可能越界。 */
p1 -= 8;
/* 4、Confirm Command */
WriteFlashStatus((_U16 *)p1, RESUME_FLASH_CMD);
t = 0;
/*按照INTEL手册上说,此时如果读到BIT7为1,
应该判断其他位是否为1,各个有各自的错误描述。
此时为0或者为1应该都可以结束。以后可以考虑删除以下代码。*/
status = ReadFlashStatus(p1);
while( ((status & BIT_7) != BIT_7)
&& (t++ <= ESR_POLLING_TIMEOUT) )
{
status = ReadFlashStatus(p1);
}
if (t >= ESR_POLLING_TIMEOUT)
{
Drv_Print("\r\n Read Flash Status Timeout!!!,%d",__LINE__);
return FAILURE;
}
p1 += 8;
}
/* Switch to read array status */
WriteFlashStatus( (_U16 *)FlashAddr, CLEAR_FLASH_STATUS ) ;
WriteFlashStatus( (_U16 *)FlashAddr, READ_FLASH_ARRAY ) ;
return(SUCCESS);
}
#else
/*****************************************************************************
function : write flash one block
return : SUCCESS if write success
FAILURE if write fail
******************************************************************************/
_U32 WriteFlashSeg( _U16 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
_U16 ucByte = 0 ;
_U32 loop = 0, cnt = 0 ;
_U16 *pucValue = 0;
pucValue = (_U16 *)RamAddr;
if (DELAY_WRITE == Drv_FlashStatus)
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
for (cnt = 0; cnt < ByteCount; cnt += 2)
{//因为采用16位操作.
/* Byte write command */
WriteFlashStatus( FlashAddr, WRITE_FLASH_BYTE ) ;
/* Actual data write to flash address */
WriteFlashStatus( FlashAddr, *pucValue ) ;
ucByte = ReadFlashStatus( FlashAddr ) ;
loop = 0 ;
/* Poll CSR until CSR.7 = 1 (WSM) */
while ((!(BIT_7 & ucByte)) && (loop ++ < ESR_POLLING_TIMEOUT))
{
if ((DELAY_WRITE == Drv_FlashStatus)&&(loop % 2048 == 0))
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
ucByte = ReadFlashStatus( FlashAddr ) ;
}
if (loop >= ESR_POLLING_TIMEOUT)
{
return FAILURE;
}
if ((DELAY_WRITE == Drv_FlashStatus)&&(cnt % (FLASH_BLOCK_SIZE/16) == 0))
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
FlashAddr++ ;
pucValue++;
}
if (DELAY_WRITE == Drv_FlashStatus)
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
FlashAddr--;
/* Switch to read array status */
WriteFlashStatus( (_U16 *)FlashAddr, CLEAR_FLASH_STATUS ) ;
WriteFlashStatus( (_U16 *)FlashAddr, READ_FLASH_ARRAY ) ;
return SUCCESS;
}
#endif
//不用擦除直接写 单字符写入
_U32 Drv_FlashTestWrite( _U8 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
_U16 ucByte = 0 ;
_U32 loop = 0, cnt = 0 ;
_U16 *pucValue = 0;
pucValue = (_U16 *)RamAddr;
if (DELAY_WRITE == Drv_FlashStatus)
{
// Drv_Print("\r\n %d",__LINE__);
(void)taskDelay(1);
}
for (cnt = 0; cnt < ByteCount; cnt += 2)
{//因为采用16位操作.
/* Byte write command */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -