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

📄 flashdrv.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 
  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 + -