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

📄 flash_nvram56xx.c

📁 GM5621原代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	// find an empty block
	// if offset is supplied, then we assume block already exists, find the
	// block if offset is not zero.
	if(W_Offset == 0x00)
		pbAddr = findBlockType(0xff, 0xff, &version);
	else
	{
		createHeader = gmd_FALSE;
		do
		{
			pbAddr = findBlockType(B_BlockType, B_Index, &version);
		}while(((DWORD)pbAddr == NULL_PTR) && (version-- != 0x00));

		if((DWORD)pbAddr == NULL_PTR)
		{// block not found, nothing we can do, find an empty block.
			createHeader = gmd_TRUE;
			pbAddr = findBlockType(0xff, 0xff, &version);
		}
	}
	msgx("B_BlockType %x",(WORD)B_BlockType);
	msgx("B_Index %x",(WORD)B_Index);
	msgx("pbAddr seg %x",(WORD)((DWORD)pbAddr >> 16));
	msgx("pbAddr off %x",(WORD)pbAddr);

	// see if there's enough room in this FLASH sector for our new block.
	room = (WORD)(HUGE((DWORD)workingSector + FLASHUserPrefSectorSize) - HUGE(pbAddr));
	msgx("room %d",(WORD)room);
	msgx("size %d",(WORD)hdr.Size);
	msgx("W_Length %d",W_Length);
	msgx("W_Offset %d",W_Offset);

	if( (room < hdr.Size) || (pbAddr == NULL_PTR) ) // not enough room.  Time to prune the sector.
	{
		msgx("..prune2..",0);
 		msgx("room %d",(WORD)room);
		msgx("size %d",(WORD)hdr.Size);


		prune();

      msgx("prune time: %d", (WORD)(t2-t1));

		// find an empty block
		pbAddr = findBlockType(0xff, 0xff, &version);
		if(pbAddr == NULL_PTR)
			return gmd_FAIL; // if after prune, still no room, nothing else we can do.
	}

   //testing
//   if(B_BlockType==ModeIndependentUserPreferences_ID)
//   	return gmd_FAIL;

	// first fill in block header.
	// if offset is supplied, then we assume block already exists, don't
	// create a new header if block already exists.
	if(createHeader)
		executeRamResidentCmd(FLASH_NV_WRITE, pbAddr, sizeof(block_hdr_type), (BYTE far *)&hdr);
	// now the data...
	executeRamResidentCmd(FLASH_NV_WRITE, &pbAddr[BLOCK_DATA_OFFSET + W_Offset], W_Length, Bp_Buffer);

	return gmd_OK;
}
//***************************************************************
// FUNCTION     :   pp_ReadNVRAMAbsolute
// DESCRIPTION  :   Read from an Absolute address.
// INPUT        :   Address, buffer pointer, length.
// OUTPUT       :   gmt_RET_STAT
// USED_REGS    :   None
//***************************************************************
gmt_RET_STAT pp_ReadNVRAMAbsolute(WORD Address, BYTE * Bp_Buffer, WORD W_Length)
{
	BYTE far *pbAddr = (BYTE far *)((DWORD)workingSector + Address);

	_fmemcpy(Bp_Buffer, pbAddr, W_Length);

	return gmd_OK;
}
//***************************************************************
// FUNCTION     :   pp_WriteNVRAMAbsolute
// DESCRIPTION  :   Write to Absolute address.
// INPUT        :   Address, buffer pointer, length.
// OUTPUT       :   gmt_RET_STAT
// USED_REGS    :   None
//***************************************************************
gmt_RET_STAT pp_WriteNVRAMAbsolute(WORD Address, BYTE * Bp_Buffer, WORD W_Length)
{
	BYTE far *pbAddr = (BYTE far *)((DWORD)workingSector + Address);


	executeRamResidentCmd(FLASH_NV_WRITE, pbAddr, W_Length, Bp_Buffer);


	return gmd_OK;
}


static BYTE far *findBlockType(BYTE blockType, BYTE blockIndex, BYTE *version)
{
	BYTE far *WrAddr, far *GoodBlock;
	DWORD LastAddress;
   DWORD DW_tmpAddress;
	WORD length;
	BYTE ver, getVer = 0;

	// allow null pointer for version.
	if(version == NULL_PTR)
	{
		ver = 0;
		version = &ver;
	}
	// if version is non-zero, then this is the version we want to get.
	if(*version)
		getVer = ~*version + 1;

	*version = 0;
	// version is used for two purposes.  If version is zero prior to entering
	// this function, than it will be incremented each time a BlockType is found.
	// This can be read later to see how many entries of this BlockType there
	// are.  When reading a block entry, and the checksum is bad, and the
	// version is greater than 1, then we know there's a backup copy somewhere
	// in the sector.  So set the version to 1 less then the number found, and
	// invert it, now when version is incremented in this function, and it hits
	// zero, then it will return this entry.  example: if looking for
	// NVRAM_MODEDEP_USERPREF, the version is 3, and the checksum is bad.
	// look for versioin 2 by inverting it and add one (0xFE) then call this
	// function again.  When it increments version up to 0x00, then that entry
	// will be returned (the 2nd entry in this example).

	WrAddr      = workingSector;
	GoodBlock 	= NULL_PTR;
	LastAddress = (DWORD)workingSector + FLASHUserPrefSectorSize;

	msgx("LastAddress seg %x",FP_SEG(LastAddress));
	msgx("LastAddress off %x",FP_OFF(LastAddress));
	msgx("findBlock %x",(WORD)blockType);


	do
	{
//msgx("WrAddr seg %x",FP_SEG(WrAddr));
//msgx("WrAddr off %x",FP_OFF(WrAddr));

		if(WrAddr[0] == blockType)
		{// look at index (first byte after Block_Type)
			if(WrAddr[1] == blockIndex)
			{
				(*version)++; // keep track of how many matching entries we've found.
				getVer++;
				GoodBlock = WrAddr;
				if((getVer == 0x00) || ((blockType == 0xff) && (blockIndex == 0xff)) )
				{  // If getVer hit's zero, than we want this paricular entry -used
					// to find backup copies of data.
					msgx("GoodBlock seg %x",(WORD)((DWORD)GoodBlock >> 16));
					msgx("GoodBlock off %x",(WORD)GoodBlock);

					return GoodBlock;
				}
			}
		}
		// else go to next block.
		length = getLength(WrAddr);

		// if length > UserPrefSectorSize, than either it's 0xffff becuase the location is blank and
		// we've reachd the end of our data, or it's corrupt, either case stop here.
		if((length > HUGE_OFF(FLASHUserPrefSectorSize)) || (length == 0x00))
		{
			msgx("length out of range %d",length);
			msgx("GoodBlock seg %x",FP_SEG(GoodBlock));
			msgx("GoodBlock off %x",FP_OFF(GoodBlock));
			msgx("WrAddr seg %x",FP_SEG(WrAddr));
			msgx("WrAddr off %x",FP_OFF(WrAddr));
			msgx("WrAddr[0] %x",(WORD)WrAddr[0]);
			msgx("WrAddr[1] %x",(WORD)WrAddr[1]);

			msgx("version %d",(WORD)*version);
			msgx("blockType  %x",(WORD)blockType);
			msgx("blockIndex %x",(WORD)blockIndex);
			return GoodBlock;
		}
		WrAddr += length;

      DW_tmpAddress = HUGE(WrAddr);
	}
	while((DW_tmpAddress < HUGE(LastAddress)) && (DW_tmpAddress > HUGE(workingSector)));// make sure still in range.


	msgx("end of sector",0);
	msgx("version %d",(WORD)*version);
	msgx("WrAddr seg %x",FP_SEG(WrAddr));
	msgx("WrAddr off %x",FP_OFF(WrAddr));
	msgx("GoodBlock seg %x",FP_SEG(GoodBlock));
	msgx("GoodBlock off %x",FP_OFF(GoodBlock));


	return GoodBlock;
}
//***************************************************************
// FUNCTION     :   prune
// USAGE        :
// DESCRIPTION  :   Copy "good" data from current sector into the
//	alternate sector, then erase the current sector. "good" data
//	refers to the latest copy of an entry.  If the user changes 
//	the ModeIndependent settings 100 times, only the last one is
//  good, so that is the only entry that is copied to the alternate
//  sector.  
// INPUT        :   WrAddr should be pointing to the head of the
//	current 'working' sector.
// OUTPUT       :   None
//***************************************************************
#if FAST_FLASH_PAGE_UPDATE

// The default buffer length is set to 256 bytes (= one page size of PMC flash).
// RAM resident command won't be called unless a buffer is almost full.  This way can dramatically reduce 
// the number of page writes and hence reduce saving time. 
#define BUFFER_LENGTH	256


//***************************************************************
// FUNCTION     :   MakeCountTable
// DESCRIPTION  :   to make count table from gmc_RomDirectory[] array.
//					The count table indicates how many nvram block entries exist before
//					current blockType, for modeDependent block, it contains more than 1 entry.
//
// INPUT        :   gmc_RomDirectory[] array in nvtable.c file, generated by Workbench
//
// OUTPUT       :   B_CountTable
//					
// RETURN		:	ret: gmd_TURE or gmd_FALSE;
//
// USED_REGS    :   None
//
// Algorithm	:	1)to derive # of entries for each block type;
//					2)to accumulate # of entries before current block type;
//NOTE	:
//	In Workbench, all NVRAM block directory should be set in ROM, that is,
//	the option "Put link in NVRAM directory" should NOT be checked. 
//	Otherwise, gmv_Size_RomDirectory wonn't reflect the total # of blockType.
//***************************************************************
static gmt_RET_STAT MakeCountTable(void)
{
	BYTE i, end;
   WORD length;
	gmt_RET_STAT ret = gmd_TRUE;

	//initialization
	_fmemset(B_CountTable, 0, MAX_BLOCK_ENTRIES);

	end = (gmv_Size_RomDirectory<MAX_BLOCK_ENTRIES?gmv_Size_RomDirectory:MAX_BLOCK_ENTRIES);

	//to derive # of entries for each block type;
	B_CountTable[0] = 0;
	msgx("B_CountTable[i]: %d", end);
	msgx("%d", B_CountTable[0]);
	for(i=1; i<end; i++)
	{
   	length = gmc_RomDirectory[i-1].length & (~CRC_FLAG);
   	if(gmc_RomDirectory[i-1].length & CRC_FLAG)
      	length += CRC_SIZE;

		if(gmc_RomDirectory[i-1].length)
			B_CountTable[i] = (BYTE)((gmc_RomDirectory[i].address - gmc_RomDirectory[i-1].address) / length);
		else
			B_CountTable[i] = 0;

		msgx("addrDiff: 0x%x", gmc_RomDirectory[i].address - gmc_RomDirectory[i-1].address);
		msgx("length: 0x%x", length);
		msgx("%d", B_CountTable[i]);
	}

	//to accumulate # of entries before current block type;
	for(i=1; i<end; i++)
	{
		B_CountTable[i] += B_CountTable[i-1];

		msgx("%d", B_CountTable[i]);
	}

	//to check buffer/array limit
	if(gmv_Size_RomDirectory > MAX_BLOCK_ENTRIES ||
	   B_CountTable[end-1] > MAX_TOTAL_INDICES)
		ret = gmd_FALSE;	//fail
	else
		ret = gmd_TRUE;

	return ret;
}

//***************************************************************
// FUNCTION     :   IsValidBlockEntry
// DESCRIPTION  :   to check whether block is valid
//
// INPUT        :   blockId, index
//
// OUTPUT       :   none
//					
// RETURN		:	ret: gmd_TURE or gmd_FALSE;
//
// NOTE    : this function skips index check for last blockType (blockId<gmv_Size_RomDirectory-1)
//
//***************************************************************
static gmt_RET_STAT IsValidBlockEntry(BYTE blockId, BYTE index)
{
	gmt_RET_STAT ret = gmd_TRUE;

	if(blockId>=gmv_Size_RomDirectory || index>=MAX_TOTAL_INDICES)
		return gmd_FALSE;

	if(blockId<gmv_Size_RomDirectory-1)
	{
		if(index < (B_CountTable[blockId+1]-B_CountTable[blockId]) )
			ret = gmd_TRUE;
		else
			ret = gmd_FALSE;
	}



	return ret;
}

//***************************************************************
// FUNCTION     :   prune
// USAGE        :
// DESCRIPTION  :   Copy "good" data from current sector into the
//	alternate sector, then erase the current sector. "good" data
//	refers to the latest copy of an entry.  This version search current
//  sector once to build W_AddrTable, then copy data to another sector
//  in page mode, the buffer size is 256 bytes by default
// INPUT        :   WrAddr should be pointing to the head of the
//	current 'working' sector.
// OUTPUT       :   None
//***************************************************************
void prune(void)
{
	WORD offset, length, offsetInBlock;
   BYTE blockType, index, pos;
   BYTE far *alternateSector, far *altPtr;
   BYTE buff[BUFFER_LENGTH];
   WORD freeSpace;
	BYTE	i;
	BYTE far *WrAddr;
	DWORD LastAddress;

	//initialize address map table with invalid address 0xffff
	_fmemset(W_AddrTable, 0xff, MAX_TOTAL_INDICES*sizeof(WORD));

⌨️ 快捷键说明

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