📄 flashdrv.c
字号:
/*****************************************************************************
FILE NAME: FlashDrv.c
DESCRIPTION:
For intel single-bank flash.
Copyright (c) 2002, VIA Technologies, Inc.
*****************************************************************************/
#include "fsmdefs.h"
#include "FsmFlash.h"
#include "intelflash.h"
#include "ostype.h"
#define BLOCK_SIZE 0x10000
#define FSM_DATA_BLOCKS 8
#define FSM_DATA_START_ADDR 0x07300000
#define GET_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define ALIGN_ADDRESS(addr) ((uint32) ((addr) & ((uint32) ~(sizeof(FLASH_DATA) - 1))))
#define UNALIGNED_BYTES(addr) ((uint32) ((addr) & ((uint32) (sizeof(FLASH_DATA) - 1))))
/* =============== local variables =========================== */
#if (RELOCATE_CODE == TRUE)
#define FUNCTION_RAM_SIZE 1024
static uint8 FsmDrvFuncBuf[FUNCTION_RAM_SIZE + 4];
extern void FsmLowerBegin(void);
extern void FsmLowerEnd(void);
#endif /* RELOCATE_CODE */
typedef uint32 (*WRITE_FUNCPTR)(volatile FLASH_DATA *, const FLASH_DATA *, uint32);
extern uint32 FsmLowerWrite(volatile FLASH_DATA *, const FLASH_DATA *, uint32);
static WRITE_FUNCPTR pLowerWrite;
typedef uint32 (*ERASE_FUNCPTR)(volatile FLASH_DATA_PTR, uint32);
extern uint32 FsmLowerErase(volatile FLASH_DATA_PTR, uint32);
static ERASE_FUNCPTR pLowerErase;
typedef FLASH_DATA (*READSTAT_FUNCPTR)(volatile FLASH_DATA_PTR);
extern FLASH_DATA FsmLowerReadStat(volatile FLASH_DATA_PTR);
static READSTAT_FUNCPTR pLowerReadStat;
typedef void (*CLEARSTAT_FUNCPTR)(volatile FLASH_DATA_PTR);
extern void FsmLowerClearStat(volatile FLASH_DATA_PTR);
static CLEARSTAT_FUNCPTR pLowerClearStat;
uint32 FsmFlashInit(FsmDevObjHdrT * DevObjP);
uint32 FsmFlashRead(FsmDevObjHdrT * DevObjP, uint8 * buf, uint32 Addr, uint32 length);
uint32 FsmFlashWrite(FsmDevObjHdrT * DevObjP, uint8 * buf, uint32 Addr, uint32 length);
uint32 FsmFlashErase(FsmDevObjHdrT * DevObjP, uint32 Addr);
uint32 FsmFlashCopy(FsmDevObjHdrT * DevObjP, uint32 DstAddr, uint32 SrcAddr, uint32 length);
uint32 FsmFlashCtrl(FsmDevObjHdrT * DevObjP, uint32 CtrlCode, void *arg);
/* =============== global variables ========================= */
const FsmDevDrvT FlashDrv = \
{
FsmFlashRead,
FsmFlashWrite,
FsmFlashCopy,
FsmFlashErase,
FsmFlashCtrl,
FsmFlashInit
};
FsmFlashDevT FlashDev =
{
{ (FsmDevDrvT *)&FlashDrv, DEV_TYPE_FLASH, NULL },
NULL,
NULL,
BLOCK_SIZE,
FSM_DATA_BLOCKS,
FSM_DATA_START_ADDR
};
extern volatile uint8 FsmStarting;
/******************************************************************************
* FsmFlashInit()
*
* descriptions:
* Initializes the function pointers used by the flash driver.
* some driver code can be located into ram if it is necessary.
*
* parameters:
* FsmDevObjHdrT * DevObjP - device object
*
* return:
* HW_ERR_NONE, HW_ERR_SYSTEM.
*
*****************************************************************************/
uint32 FsmFlashInit(FsmDevObjHdrT * DevObjP)
{
/* FsmFlashDevT * pFlashDev = (FsmFlashDevT *)DevObjP; */
#if (RELOCATE_CODE == TRUE)
uint8 * pSrc = (uint8 *)FsmLowerBegin;
uint16 size = (uint16)((uint32)FsmLowerEnd - (uint32)FsmLowerBegin);
uint32 StartAddr;
uint8 * pDst;
uint32 offset;
if(size > FUNCTION_RAM_SIZE)
{
return HW_ERR_SYSTEM;
}
/* Aligned the dst pointer on 4-Byte boundary */
StartAddr = (uint32)(((uint32)FsmDrvFuncBuf) & (~0x03));
pDst = (uint8 *)StartAddr;
/*
* the following codes are needed when the target cpu is ARM
* and the embedded system is compiled using interworking option.
*
* It is used to modify the bit0 of the function pointer.
*/
/*------------------------begin--------------------------------*/
StartAddr |= (((uint32)pSrc) & 0x01);
pSrc = (uint8 *)(((uint32)pSrc) & (~0x01));
/*-------------------------end---------------------------------*/
/* Download some driver code into ram. */
FsmMemoryMove(pDst, pSrc, size);
/* initialize function pointrs. */
offset = (uint32)FsmLowerWrite - (uint32)FsmLowerBegin;
pLowerWrite = (WRITE_FUNCPTR)(StartAddr + offset);
offset = (uint32)FsmLowerErase - (uint32)FsmLowerBegin;
pLowerErase = (ERASE_FUNCPTR)(StartAddr + offset);
offset = (uint32)FsmLowerReadStat - (uint32)FsmLowerBegin;
pLowerReadStat = (READSTAT_FUNCPTR)(StartAddr + offset);
offset = (uint32)FsmLowerClearStat - (uint32)FsmLowerBegin;
pLowerClearStat = (CLEARSTAT_FUNCPTR)(StartAddr + offset);
#else /* RELOCATE_CODE != TRUE */
pLowerWrite = (WRITE_FUNCPTR) FsmLowerWrite;
pLowerErase = (ERASE_FUNCPTR) FsmLowerErase;
pLowerReadStat = (READSTAT_FUNCPTR) FsmLowerReadStat;
pLowerClearStat = (CLEARSTAT_FUNCPTR) FsmLowerClearStat;
#endif /* !RELOCATE_CODE */
/* Initialize Device object... */
return HW_ERR_NONE;
}
/******************************************************************************
* FsmFlashRead()
*
* descriptions:
* reset flash device to read-mode.
*
* parameters:
* FsmDevObjHdrT * DevObjP - device object
* uint8 * buf - buffer to receive the returned data
* uint32 Addr - where to read from within flash.
* uint32 length - number of bytes to read.
*
* return:
* HW_ERR_NONE.
*
*****************************************************************************/
uint32 FsmFlashRead(FsmDevObjHdrT * DevObjP, uint8 * buf, uint32 Addr, uint32 length)
{
uint8 * src_byte_ptr;
uint8 * dst_byte_ptr;
FLASH_DATA_PTR src_data_ptr;
FLASH_DATA_PTR dst_data_ptr;
uint32 src_offset;
uint32 dst_offset;
FsmFlashDevT * pDev;
pDev = (FsmFlashDevT *)DevObjP;
/* validate address */
#ifdef VALIDATE_ADDRESS
if((Addr + length) > (pDev->BlockSize * pDev->Blocks))
{
return HW_ERR_PARAM;
}
#endif //VALIDATE_ADDRESS
Addr += pDev->DevStartAddr;
/* return if nothing to read */
if (length == 0)
{
return HW_ERR_NONE;
}
/* determine address offsets */
src_offset = UNALIGNED_BYTES(Addr);
dst_offset = UNALIGNED_BYTES((uint32)buf);
src_byte_ptr = (uint8 *) Addr;
dst_byte_ptr = buf;
/*
* determine if source and destination addresses allow the reading on
* aligned addresses
*/
if ((src_offset == dst_offset) && (length > sizeof(FLASH_DATA)))
{
/* read initial unaligned bytes */
if (src_offset != 0)
{
while (src_offset < sizeof(FLASH_DATA))
{
*dst_byte_ptr = *src_byte_ptr;
dst_byte_ptr++;
src_byte_ptr++;
length--;
src_offset++;
}
}
/* read aligned data */
dst_data_ptr = (FLASH_DATA_PTR) dst_byte_ptr;
src_data_ptr = (FLASH_DATA_PTR) src_byte_ptr;
while (length >= sizeof(FLASH_DATA))
{
*dst_data_ptr = *src_data_ptr;
dst_data_ptr++;
src_data_ptr++;
length -= sizeof(FLASH_DATA);
}
/* read remaining unaligned bytes */
if (length > 0)
{
dst_byte_ptr = (uint8 *) dst_data_ptr;
src_byte_ptr = (uint8 *) src_data_ptr;
while (length > 0)
{
*dst_byte_ptr = *src_byte_ptr;
dst_byte_ptr++;
src_byte_ptr++;
length--;
}
}
}
/*
* source and destination addresses do not allow the reading on aligned
* addresses; therefore, a byte-by-byte copy needs to be done
*/
else
{
while (length > 0)
{
*dst_byte_ptr = *src_byte_ptr;
dst_byte_ptr++;
src_byte_ptr++;
length--;
}
}
return HW_ERR_NONE;
}
/******************************************************************************
* FsmFlashWrite()
*
* descriptions:
* write data to flash.
*
* parameters:
* FsmDevObjHdrT * DevObjP - device object
* uint8 * buf - buffer contains the data to be written.
* uint32 Addr - the destination address within flash device.
* uint32 length - The amount of data, in bytes, to be written.
*
* return:
* HW_ERR_NONE, HW_ERR_SYSTEM, HW_ERR_PARAM, HW_ERR_WRITE.
*
*****************************************************************************/
uint32 FsmFlashWrite(FsmDevObjHdrT * DevObjP, uint8 * buf, uint32 Addr, uint32 length)
{
FLASH_DATA_PTR src_data_ptr;
FLASH_DATA_PTR dst_data_ptr;
uint8 * src_byte_ptr;
uint8 * dst_byte_ptr;
uint32 src_offset;
uint32 dst_offset;
uint32 init_unaligned_bytes;
FLASH_DATA temp_data;
uint32 status = HW_ERR_NONE;
FsmFlashDevT * pDev;
/* power loss simulation for testing purposes */
pDev = (FsmFlashDevT *)DevObjP;
/* validate address */
#ifdef VALIDATE_ADDRESS
if((Addr + length) > (pDev->BlockSize * pDev->Blocks))
{
return HW_ERR_PARAM;
}
#endif //VALIDATE_ADDRESS
Addr += pDev->DevStartAddr;
/* return if nothing to write */
if (length == 0)
{
return HW_ERR_NONE;
}
/* align addresses & determine address offset */
dst_data_ptr = (FLASH_DATA_PTR) ALIGN_ADDRESS(Addr);
src_offset = UNALIGNED_BYTES((uint32) buf);
dst_offset = UNALIGNED_BYTES(Addr);
dst_byte_ptr = (BYTE_PTR) &temp_data + dst_offset;
/* calculate the number of initial unaligned bytes */
if (src_offset == dst_offset)
{
if (dst_offset == 0)
{
init_unaligned_bytes = 0;
}
else
{
init_unaligned_bytes = GET_MIN(length, sizeof(FLASH_DATA) - dst_offset);
}
}
else
{
init_unaligned_bytes = length;
}
length -= init_unaligned_bytes;
/* take flash write mutex. */
if(FsmGetMtxSem(pDev->DevWriteLock) != ERR_NONE)
{
if(FsmStarting == FALSE)
return HW_ERR_SYSTEM;
}
/*
* write initial unaligned data, or all data if source and destination
* addresses do not have the same offset
*/
src_byte_ptr = (BYTE_PTR) buf;
while ((init_unaligned_bytes > 0) && (status == HW_ERR_NONE))
{
/* fill temp buffer with data */
if(dst_offset != 0)
{
FsmMemoryMove((BYTE_PTR)(&temp_data), (BYTE_PTR)dst_data_ptr, dst_offset);
}
while ((dst_offset < sizeof(FLASH_DATA)) && (init_unaligned_bytes > 0))
{
*dst_byte_ptr = *src_byte_ptr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -