📄 osal_nv.c
字号:
(((id & 0x8000) != 0) && (hdr.stat != OSAL_NV_ERASED_ID)) )
{
return offset;
}
}
}
// When invoked from the osal_nv_init(), find and zero any duplicates.
else if ( hdr.stat == OSAL_NV_ERASED_ID )
{
/* The trick of setting the MSB of the item Id causes the logic
* immediately above to return a valid page only if the header 'stat'
* indicates that it was the older item being transferred.
*/
uint16 off = findItem( (hdr.id | 0x8000) );
if ( off != OSAL_NV_ITEM_NULL )
{
setItem( findPg, off, eNvZero ); // Mark old duplicate as invalid.
}
}
}
else
{
setItem( pg, offset, eNvZero ); // Mark bad checksum as invalid.
}
}
if ( hdr.id == OSAL_NV_ZEROED_ID )
{
lost += (OSAL_NV_HDR_SIZE + sz);
}
offset += sz;
} while ( TRUE );
pgOff[pg - OSAL_NV_PAGE_BEG] = offset;
pgLost[pg - OSAL_NV_PAGE_BEG] = lost;
return OSAL_NV_ITEM_NULL;
}
/*********************************************************************
* @fn erasePage
*
* @brief Erases a page in Flash.
*
* @param pg - Valid NV page to erase.
*
* @return none
*/
static void erasePage( uint8 pg )
{
osalNvHdr_t ieee;
if ( !OSAL_NV_CHECK_BUS_VOLTAGE )
{
failF = TRUE;
return;
}
OSAL_NV_PAGE_ERASE( pg );
pgOff[pg - OSAL_NV_PAGE_BEG] = OSAL_NV_PAGE_HDR_SIZE;
pgLost[pg - OSAL_NV_PAGE_BEG] = 0;
readHdr( OSAL_NV_IEEE_PAGE, OSAL_NV_IEEE_OFFSET, (uint8 *)(&ieee) );
if ( (ieee.id != OSAL_NV_ERASED_ID) ||
(ieee.len != OSAL_NV_ERASED_ID) ||
(ieee.chk != OSAL_NV_ERASED_ID) ||
(ieee.stat != OSAL_NV_ERASED_ID) )
{
writeWordD( pg, OSAL_NV_IEEE_OFFSET, (uint8 *)(&ieee) );
}
}
/*********************************************************************
* @fn compactPage
*
* @brief Compacts the page specified.
*
* @param srcPg - Valid NV page to erase.
*
* @return none
*/
static void compactPage( uint8 srcPg )
{
uint16 dstOff = pgOff[pgRes-OSAL_NV_PAGE_BEG];
uint16 srcOff = OSAL_NV_ZEROED_ID;
osalNvHdr_t hdr;
// Mark page as being in process of compaction.
writeWordH( srcPg, OSAL_NV_PG_XFER, (uint8*)(&srcOff) );
srcOff = OSAL_NV_PAGE_HDR_SIZE;
do
{
uint16 sz;
readHdr( srcPg, srcOff, (uint8 *)(&hdr) );
if ( hdr.id == OSAL_NV_ERASED_ID )
{
break;
}
srcOff += OSAL_NV_HDR_SIZE;
if ( (srcOff + hdr.len) > OSAL_NV_PAGE_FREE )
{
break;
}
sz = ((hdr.len + (OSAL_NV_WORD_SIZE-1)) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE;
if ( hdr.id != OSAL_NV_ZEROED_ID )
{
if ( hdr.chk == calcChkF( srcPg, srcOff, hdr.len ) )
{
setItem( srcPg, srcOff, eNvXfer );
writeBuf( pgRes, dstOff, OSAL_NV_HDR_SIZE, (byte *)(&hdr) );
dstOff += OSAL_NV_HDR_SIZE;
xferBuf( srcPg, srcOff, pgRes, dstOff, sz );
dstOff += sz;
}
setItem( srcPg, srcOff, eNvZero ); // Mark old location as invalid.
}
srcOff += sz;
} while ( TRUE );
pgOff[pgRes-OSAL_NV_PAGE_BEG] = dstOff;
/* In order to recover from a page compaction that is interrupted,
* the logic in osal_nv_init() depends upon the following order:
* 1. Compacted page is erased.
* 2. State of the target of compaction is changed ePgActive to ePgInUse.
*/
erasePage( srcPg );
// Mark the reserve page as being in use.
setPageUse( pgRes, TRUE );
// Mark newly erased page as the new reserve page.
pgRes = srcPg;
}
/*********************************************************************
* @fn findItem
*
* @brief Find an item Id in NV and return the page and offset to its data.
*
* @param id - Valid NV item Id.
*
* @return Offset of data corresponding to item Id, if found;
* otherwise OSAL_NV_ITEM_NULL.
*
* The page containing the item, if found;
* otherwise no valid assignment made - left equal to item Id.
*
*/
static uint16 findItem( uint16 id )
{
uint16 off;
uint8 pg;
for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
{
if ( (off = initPage( pg, id )) != OSAL_NV_ITEM_NULL )
{
findPg = pg;
return off;
}
}
// Now attempt to find the item as the "old" item of a failed/interrupted NV write.
for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
{
if ( (off = initPage( pg, (id | 0x8000) )) != OSAL_NV_ITEM_NULL )
{
findPg = pg;
return off;
}
}
findPg = OSAL_NV_PAGE_NULL;
return OSAL_NV_ITEM_NULL;
}
/*********************************************************************
* @fn initItem
*
* @brief An NV item is created and initialized with the data passed to the function, if any.
*
* @param id - Valid NV item Id.
* @param len - Item data length.
* @param *buf - Pointer to item initalization data. Set to NULL if none.
*
* @return TRUE if item write and read back checksums ok; FALSE otherwise.
*/
static uint8 initItem( uint16 id, uint16 len, void *buf )
{
uint16 sz = ((len + (OSAL_NV_WORD_SIZE-1)) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE +
OSAL_NV_HDR_SIZE;
uint8 pg = OSAL_NV_PAGE_BEG;
uint8 rtrn = FALSE;
uint8 idx;
for ( idx = 0; idx < OSAL_NV_PAGES_USED; idx++, pg++ )
{
if ( pg == pgRes )
{
continue;
}
if ( (pgOff[idx] - pgLost[idx] + sz) <= OSAL_NV_PAGE_FREE )
{
break;
}
}
if ( idx != OSAL_NV_PAGES_USED )
{
// Item fits if an old page is compacted.
if ( (pgOff[idx] + sz) > OSAL_NV_PAGE_FREE )
{
pg = pgRes;
}
// New item is the first one written to the reserved page, then the old page is compacted.
if ( writeItem( pg, id, len, buf ) )
{
rtrn = TRUE;
}
if ( pg == pgRes )
{
compactPage( OSAL_NV_PAGE_BEG+idx );
}
}
return rtrn;
}
/*********************************************************************
* @fn initItem2
*
* @brief An NV item is created.
*
* @param id - Valid NV item Id.
* @param len - Item data length.
*
* @return TRUE if item write and read back checksums ok; FALSE otherwise.
* If return it TRUE, then findPg is set to OSAL_NV_PAGE_NULL if a page compaction is not
* required; otherwise it is set to the non-NULL page that must be compacted.
*/
static uint8 initItem2( uint16 id, uint16 len, uint8 *comPg )
{
uint16 sz = ((len + (OSAL_NV_WORD_SIZE-1)) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE +
OSAL_NV_HDR_SIZE;
uint8 pg = OSAL_NV_PAGE_BEG;
uint8 idx;
for ( idx = 0; idx < OSAL_NV_PAGES_USED; idx++, pg++ )
{
if ( pg == pgRes )
{
continue;
}
if ( (pgOff[idx] - pgLost[idx] + sz) <= OSAL_NV_PAGE_FREE )
{
break;
}
}
// Item fits if an old page is compacted.
if ( (idx == OSAL_NV_PAGES_USED) || ((pgOff[idx] + sz) > OSAL_NV_PAGE_FREE) )
{
pg = pgRes;
if ( idx != OSAL_NV_PAGES_USED )
{
*comPg = OSAL_NV_PAGE_BEG+idx;
}
else
{
// comPg has already been set to the page containing the item, so compact that one.
}
}
if ( writeItem( pg, id, len, NULL ) )
{
return pg;
}
else
{
return OSAL_NV_PAGE_NULL;
}
}
/*********************************************************************
* @fn setItem
*
* @brief Set an item Id or status to mark its state.
*
* @param pg - Valid NV page.
* @param offset - Valid offset into the page of the item data - the header
* offset is calculated from this.
* @param stat - Valid enum value for the item status.
*
* @return none
*/
static void setItem( uint8 pg, uint16 offset, eNvHdrEnum stat )
{
osalNvHdr_t hdr;
offset -= OSAL_NV_HDR_SIZE;
readHdr( pg, offset, (uint8 *)(&hdr) );
if ( stat == eNvXfer )
{
hdr.stat = OSAL_NV_ACTIVE;
writeWord( pg, offset+OSAL_NV_HDR_CHK, (uint8*)(&(hdr.chk)) );
}
else // if ( stat == eNvZero )
{
uint16 sz = ((hdr.len + (OSAL_NV_WORD_SIZE-1)) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE +
OSAL_NV_HDR_SIZE;
hdr.id = 0;
writeWord( pg, offset, (uint8 *)(&hdr) );
pgLost[pg-OSAL_NV_PAGE_BEG] += sz;
}
}
/*********************************************************************
* @fn calcChkB
*
* @brief Calculates the data checksum over the 'buf' parameter.
*
* @param pg - A valid NV Flash page.
* @param offset - A valid offset into the page.
* @param len - Byte count of the data to be checksummed.
*
* @return Calculated checksum of the data bytes.
*/
static uint16 calcChkB( uint16 len, uint8 *buf )
{
uint16 chk = 0;
while ( len-- )
{
chk += *buf++;
}
return chk;
}
/*********************************************************************
* @fn calcChkF
*
* @brief Calculates the data checksum by reading the data bytes from NV.
*
* @param pg - A valid NV Flash page.
* @param offset - A valid offset into the page.
* @param len - Byte count of the data to be checksummed.
*
* @return Calculated checksum of the data bytes.
*/
static uint16 calcChkF( byte pg, uint16 offset, uint16 len )
{
uint32 addr = OSAL_NV_PAGE_TO_ADDR( pg ) + offset;
uint16 chk = 0;
uint8 eFlag = TRUE;
while ( len-- )
{
uint8 ch = GetCodeByte( addr++ );
if ( ch != OSAL_NV_ERASED )
{
eFlag = FALSE;
}
chk += ch;
}
if ( eFlag )
{
return OSAL_NV_ERASED_ID;
}
else
{
return chk;
}
}
/*********************************************************************
* @fn readHdr
*
* @brief Reads "sizeof( osalNvHdr_t )" bytes from NV.
*
* @param pg - Valid NV page.
* @param offset - Valid offset into the page.
* @param buf - Valid buffer space of at least sizeof( osalNvHdr_t ) bytes.
*
* @return none
*/
static void readHdr( uint8 pg, uint16 offset, uint8 *buf )
{
uint32 addr = OSAL_NV_PAGE_TO_ADDR( pg ) + offset;
uint8 len = OSAL_NV_HDR_SIZE;
do
{
*buf++ = GetCodeByte( addr++ );
} while ( --len );
}
/*********************************************************************
* @fn readWord
*
* @brief Reads "sizeof( osalNvHdr_t )" bytes from NV.
*
* @param pg - Valid NV page.
* @param offset - Valid offset into the page.
* @param buf - Valid buffer space of at least sizeof( osalNvHdr_t ) bytes.
*
* @return none
*/
static void readWord( uint8 pg, uint16 offset, uint8 *buf )
{
uint32 addr = OSAL_NV_PAGE_TO_ADDR( pg ) + offset;
uint8 len = OSAL_NV_WORD_SIZE;
do
{
*buf++ = GetCodeByte( addr++ );
} while ( --len );
}
/*********************************************************************
* @fn writeWord
*
* @brief Writes a Flash-WORD to NV.
*
* @param pg - A valid NV Flash page.
* @param offset - A valid offset into the page.
* @param buf - Pointer to source buffer.
*
* @return none
*/
static void writeWord( uint8 pg, uint16 offset, uint8 *buf )
{
if ( (buf[0] != OSAL_NV_ERASED) || (buf[1] != OSAL_NV_ERASED) ||
(buf[2] != OSAL_NV_ERASED) || (buf[3] != OSAL_NV_ERASED) )
{
offset = (offset >> 2) + ((uint16)pg << 9);
FADDRL = (uint8)offset;
FADDRH = (uint8)(offset >> 8);
FBuff[0] = buf[0];
FBuff[1] = buf[1];
FBuff[2] = buf[2];
FBuff[3] = buf[3];
execDMA();
}
}
/*********************************************************************
* @fn writeWordD
*
* @brief Writes two Flash-WORDs to NV.
*
* @param pg - A valid NV Flash page.
* @param offset - A valid offset into the page.
* @param buf - Pointer to source buffer.
*
* @return none
*/
static void writeWordD( uint8 pg, uint16 offset, uint8 *buf )
{
writeWord( pg, offset, buf );
writeWord( pg, offset+OSAL_NV_WORD_SIZE, buf+OSAL_NV_WORD_SIZE);
}
/*********************************************************************
* @fn writeWordH
*
* @brief Writes the 1st half of a Flash-WORD to NV (filling 2nd half with 0xffff).
*
* @param pg - A valid NV Flash page.
* @param offset - A valid offset into the page.
* @param buf - Pointer to source buffer.
*
* @return none
*/
static void writeWordH( uint8 pg, uint16 offset, uint8 *buf )
{
uint8 tmp[4];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -