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

📄 osal_nv.c

📁 用IAR开发的ZIGBEE网络路由例子
💻 C
📖 第 1 页 / 共 3 页
字号:
                 (((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 + -