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

📄 flash_nvram56xx.c

📁 GM5621原代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
	$Workfile:   flash_nvram56xx.c  $
	$Revision:   1.22  $
	$Date:   Aug 23 2006 23:25:24  $
*/
//******************************************************************
//
//          Copyright (C) 2001. GENESIS MICROCHIP INC.
//  All rights reserved.  No part of this program may be reproduced.
//
//  Genesis Microchip Inc., 165 Commerce Valley Dr. West
//          Thornhill, Ontario, Canada, L3T 7V8
//			Genesis Microchip Corp., 2150 Gold Street
//					Alviso, CA 95002	USA
//
//================================================================
//
//  MODULE: flash_nvram.c
//
//  USAGE : This module maintains NVRAM block data in FLASH rather than
//			EEPROM based NVRAM.  The main difference being that FLASH can
//       only be erased a minimum of 1 sector (typically 4KB) were EEPROM
//			based NVRAM can be byte erasable, allowing for a more random access
//       approach to memory management.
//       The FLASH approach to memory management is to never erase a sector
//       until it becomes full.  If a block is saved, it is simply appended
//       to the end, and when it is to be accessed, it's the last copy that
//       is the most recent.  When the sector becomes full, a prune operation
//       takes place where a second sector is erased, and only the most
//       recent block data is copied into the new sector.  The new sector//       becomes the "working" sector, and will be pruned when it becomes full.
//
//******************************************************************


//******************************************************************
//                  I N C L U D E    F I L E S
//******************************************************************
#include "..\inc\all.h"

#if USE_FLASHSPEED_AUTODETECT || NVRAM_USE_FLASH

#include "flash_hex56xx.h"
#include "mem.h"
#include "dos.h"
#include ".\system\Mcu186.h"

//******************************************************************
//              L O C A L    D E F I N I T I O N S
//******************************************************************
#define DEBUG_FLASH_NV    			0
#define DEBUG_FLASH_NV_EXTENDED  0
#define DEBUG_FLASH_INP				0


#if DEBUG_FLASH_NV && DEBUG_MSG
	#define	msg(a,b)	gm_Print((const char far *)a,b)
#else
	#define msg(a,b)
#endif
#if DEBUG_FLASH_NV_EXTENDED && DEBUG_MSG
	#define	msgx(a,b)	gm_Print((const char far *)a,b)
#else
	#define msgx(a,b)
#endif

#if DEBUG_FLASH_INP && DEBUG_MSG
	#define	inp_msg(a,b)	gm_Print((const char far *)a,b)
#else
	#define inp_msg(a,b)
#endif

#define LAST_BLOCK_ID	gmv_Size_RomDirectory //used to speed up prune routine, don't
// bother searching for all 0x00 -> 0xff block types if they're not used.

/********  NOTE **************************************************************
	The #defines below for sector size and start must be in 'HUGE' format, or
	normalized 'far' format.  Examples of far pointers and their normalized
	equivalents:
	  far       normalized
	---------   -----------
	0000:0123牋牋0012:0003
	0040:0056牋牋0045:0006
	500D:9407牋牋594D:0007
	7418:D03F牋牋811B:000F
	0000:1000    0100:0000 <- Example of 4KB sector size that's normalized
******************************************************************************/

#ifdef PHOENIX
#if FLASH_TYPE == PM39F010
	#define FLASHUserPrefSectorStartD		0x9D000000UL // use last two banks (normalized)
	#define FLASHUserPrefSectorSizeD 		0x01000000UL // 4KB sector size. (normalized)
#elif FLASH_TYPE == PM39F020
	#define FLASHUserPrefSectorStartD		0xB5000000UL // use last two banks (normalized)
	#define FLASHUserPrefSectorSizeD 		0x01000000UL // 4KB sector size. (normalized)
#elif FLASH_TYPE == SPI_FLASH
	#define FLASHUserPrefSectorStartS128	0x9D000000UL // use last two banks (normalized) for size = 128K
	#define FLASHUserPrefSectorStartS256	0xBD000000UL // use last two banks (normalized) for size = 256K
	#define FLASHUserPrefSectorStartS512	0xED000000UL // use last two banks (normalized) for size = 512K
	#define FLASHUserPrefSectorSizeS4 		0x01000000UL // 4KB sector size. (normalized)
//	#define FLASHUserPrefSectorStartST		0xA0000000UL // use last two banks (normalized) for ST (size 256K)
//	#define FLASHUserPrefSectorSizeST 		0x10000000UL // 64KB sector size. (normalized)  for ST
//	#define FLASHUserPrefSectorStartS1		0x80400000UL // use two 1K sectors in sector0, start from 2nd sector
//	#define FLASHUserPrefSectorSizeS1 		0x00400000UL // 1KB sector size. (normalized)
#else
	#error "FLASH_TYPE Uknown!"
#endif
#else		// PHOENIX
#if FLASH_TYPE == PM39F010
	#define FLASHUserPrefSectorStartD		0x9E000000UL // use last two banks (normalized)
	#define FLASHUserPrefSectorSizeD 		0x01000000UL // 4KB sector size. (normalized)
#elif FLASH_TYPE == PM39F020
	#define FLASHUserPrefSectorStartD		0xB6000000UL // use last two banks (normalized)
	#define FLASHUserPrefSectorSizeD 		0x01000000UL // 4KB sector size. (normalized)
#elif FLASH_TYPE == SPI_FLASH
	#define FLASHUserPrefSectorStartS128	0x9E000000UL // use last two banks (normalized) for size = 128K
	#define FLASHUserPrefSectorStartS256	0xBE000000UL // use last two banks (normalized) for size = 256K
	#define FLASHUserPrefSectorStartS512	0xEE000000UL // use last two banks (normalized) for size = 512K
	#define FLASHUserPrefSectorSizeS4 		0x01000000UL // 4KB sector size. (normalized)
//	#define FLASHUserPrefSectorStartST		0xA0000000UL // use last two banks (normalized) for ST (size 256K)
//	#define FLASHUserPrefSectorSizeST 		0x10000000UL // 64KB sector size. (normalized)  for ST
#else
	#error "FLASH_TYPE Uknown!"
#endif
#endif	// PHOENIX

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//NOTE: Macor HUGE_OFF and HUGE assumes normalized 32-bit address as an input;
//  Otherwise, the macros will give wrong results! Only when computing Size, Room
//  or comparing address, converting the normalized 32-bit adddress to 20-bit address
//  first by using HUGE; In all other cases, keep normalized 32-bit address!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define HUGE_OFF(a) (WORD)(((((a)>>12)&0xfff0) + FP_OFF(a)))
#define HUGE(a) (DWORD)(  (((DWORD)(a)>>12)&0xffff0UL) + (((DWORD)(a))&0xFFFFUL))


typedef enum {
	FLASH_NV_WRITE,
	FLASH_NV_SECTOR_ERASE,
	FLASH_NV_AUTODETECT,
	FLASH_NV_PROTECT,
	FLASH_NV_UNPROTECT
} flash_nv_cmd;

// Moved to Nvram_def.h file
#if 0
typedef struct block_hdr_struct
{
	BYTE	Type;		// Block_ID
	BYTE	Index;   		// Block_Index
	WORD	Size;    		// Size of Block including header
	BYTE  	Checksum; 	// Checksum.
}block_hdr_type;
#endif

#define BLOCK_TYPE_OFFSET			0
#define BLOCK_INDEX_OFFSET       		1
#define BLOCK_SIZE_OFFSET        		2
#define BLOCK_CHECKSUM_OFFSET    	4
#define BLOCK_DATA_OFFSET        		5

extern BYTE DecompBuf[768];

BYTE B_FlashChipID;		// flash chip type

DWORD FLASHUserPrefSectorStart;
DWORD FLASHUserPrefSectorSize;

typedef union
{
	DWORD DW_Addr;
	BYTE  B_A[4];

} ADDRESS;

typedef union
{
	WORD W_Word;
	BYTE B_A[2];
} WORDTOBYTE;

typedef void far(*RamResidentEntry)(BYTE cmd, BYTE far *WrAddr, WORD length, BYTE far *buff);
#if NVRAM_USE_FLASH
	#if FAST_FLASH_PAGE_UPDATE
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//NOTE:  To optimize memory usage and speed up searching,
	//			MAX_BLOCK_ENTRIES and MAX_TOTAL_INDICES has to be manually derived from nvtable.c file,
	//			make: MAX_BLOCK_ENTRIES = gmv_Size_RomDirectory, and
	//					MAX_TOTAL_INDICES = # of total entries in gmc_RomDirectory[] array
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	#define MAX_BLOCK_ENTRIES		20		//maximum # of nvram blockType
	#define MAX_TOTAL_INDICES		100	//maximum # of total individual nvram blocks (different index count as 1)

	//local
	static BYTE	B_CountTable[MAX_BLOCK_ENTRIES];
	static WORD	W_AddrTable[MAX_TOTAL_INDICES];

	//extern variables
	extern gmt_BLOCKINFO ROM gmc_RomDirectory[];
	extern BYTE ROM gmv_Size_RomDirectory;

	static gmt_RET_STAT MakeCountTable(void);
	#endif

	static WORD getLength(BYTE far *addr);
	static BYTE far *findBlockType(BYTE blockType, BYTE blockIndex, BYTE *version);
	void prune(void);
	static void findWorkingSector(void);
	static BYTE checkChecksum(BYTE far * blockAddr);
#endif //!NVRAM_USE_FLASH
gmt_BLOCKINFO	block_info; // WORD address, WORD length
BYTE far *workingSector;   // current FLASH sector in use.

//******************************************************************
//                          C O D E
//******************************************************************
static void executeRamResidentCmd(flash_nv_cmd cmd, BYTE far *WrAddr, WORD length, BYTE far *buff);


//Added function to set optimal SPI clock based on flash type after AutoDetect or know which flash type
//*********************************************************************************************
// FUNCTION     :   SetOptimizedSPIClock(void)
// DESCRIPTION  :   to set optimal SPI clock based on flash type
// INPUT        :   B_FlashChipID
//
// OUTPUT       :   None
// USED_REGS    :   None
//*********************************************************************************************
//Note: only call this function or after flash type is known, and there is a limitation for
//speed setting according to flash chipID since some flash with the same chipID may have different
//speed. System maker has to check whether this mechanism can be used or not before enable this option
#if (DISABLE_AUTODETECT == 0) && (USE_FLASHSPEED_AUTODETECT==1)
gmt_RET_STAT SetOptimalSPIClock(void)
{

		BYTE B_FlashClockInMHz;	// flash clock;
      BYTE B_tmpDivisor;

		switch(B_FlashChipID)
		{
			case SST25VF010_ID:
					msgx("SST",0);
				B_FlashClockInMHz = 20;
					break;
			case PM25LV010_ID:
					msgx("PMC",0);
				B_FlashClockInMHz = 25;
					break;
			case WB25X00_ID:				
					msgx("WB",0);
				B_FlashClockInMHz = 25;
					break;
			case STM25PExx_ID:				
					msgx("ST_PE",0);
               B_FlashClockInMHz = 20;
			   		break;
			case ST0000000_ID:				
					msgx("ST",0);
               B_FlashClockInMHz = 20;
					break;					
			default:
					msg("Error - B_FlashChipID is wrong !",B_FlashChipID);
//				B_FlashClockInMHz = 20;					
					return gmd_FALSE;
		};

      //reset gmc_SPI_Clock_Sel based on flash clock
      if( (CPU_CLK_MHZ / B_FlashClockInMHz) > 2)
      {
      	B_tmpDivisor =  (BYTE)( (10*CPU_CLK_MHZ+9*B_FlashClockInMHz)/(10UL*B_FlashClockInMHz) - 2);
         gmc_SPI_Clock_Sel = (B_tmpDivisor<<4);
      }
      else
      {
      	gmc_SPI_Clock_Sel = 0;
      }

	  gm_ClearAndSetBitsByte(SPI_CONTROL, SPI_CLK_SEL ,gmc_SPI_Clock_Sel);
	  msg("Detect and Set SPI Clock = %d Mhz-----", B_FlashClockInMHz);
	  return gmd_TRUE;
}

gmt_RET_STAT AutoDetectAndSetSpiClock(void)
{
	BYTE far *Bp_Buff = &B_FlashChipID;
	
	executeRamResidentCmd(FLASH_NV_AUTODETECT, NULL_PTR, 0, Bp_Buff);
	B_FlashChipID	= ( B_FlashChipID & 0x0F );

	msg("B_FlashChipID = %x",B_FlashChipID);

   //set optimal clock based on flash type
	return SetOptimalSPIClock();	
}

#endif //(DISABLE_AUTODETECT == 0)

//***************************************************************
// FUNCTION     :   executeRamResidentCmd
// DESCRIPTION  :   copies RAM resident code to RAM buffer and executes code.
//						  FLASH_NV_WRITE -> write contents of buffer to flash WrAddr
//						  FLASH_NV_SECTOR_ERASE -> erases sector at addres WrAddr.
// INPUT        :   cmd, WrAddr, Length, buffer.
// OUTPUT       :   gmt_RET_STAT
// USED_REGS    :   None
//***************************************************************

#if( FLASH_TYPE == SPI_FLASH )
#define ENABLE_INT()	asm{ STI }		// Enable all interrupts

static void executeRamResidentCmd(flash_nv_cmd cmd, BYTE far *WrAddr, WORD length, BYTE far *buff)
{
	DWORD DW_WrAddr = ((DWORD) WrAddr) & 0xFF000000UL;
	RamResidentEntry RamEntry = (RamResidentEntry)&DecompBuf[0];
   BYTE B_CacheCtrl;
   WORD far *pW_Cache = (WORD far *) 0x0000A800UL;
   WORD W_DummyCount;
   DWORD DW_tmpAddr;

   //Stop vblank ISR to avoid horizontal bar garbage during saving data to flash
   StopADCCalibrationISR();

   DW_tmpAddr = HUGE(WrAddr);
	if( (DW_tmpAddr < HUGE(FLASHUserPrefSectorStart)) || ((DW_tmpAddr + length) > HUGE(FLASHUserPrefSectorStart + 2 * FLASHUserPrefSectorSize) ) )
	{
		if(cmd < FLASH_NV_AUTODETECT)
		{
			inp_msg("ERROR: Attempt of write to the wrong address in the flash (ignored)",0);
			inp_msg("Address High = %x", (WORD)(((unsigned long)WrAddr) >> 16));
			inp_msg("Address Low = %x", (WORD)WrAddr);
			return;
		}
	}

	if(FLASH_NV_AUTODETECT == cmd)
	{
		msg("AUTODETECT",0);
		#if(DISABLE_AUTODETECT == 0)
		_fmemcpy(&DecompBuf[0],&RamResidentCode_AutoDetect[0],sizeof(RamResidentCode_AutoDetect));
		#else
		msg("Error - AUTODETECT is disabled !",0);
		return;
		#endif
	}
#if NVRAM_USE_FLASH	
	else

⌨️ 快捷键说明

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