This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2652P: Hot-NV-item on zstack

Part Number: CC2652P

I have managed to add hot-nv-item on zstack, and set "ZCD_NV_NWKKEY", "ZCD_NV_NWK_ACTIVE_KEY_INFO" , "ZCD_NV_NWK_ALTERN_KEY_INFO" as hot-NV-item. Now the latency of "AF_DataRequest" was reduced from 10ms to 1ms. 

And Now, I have try to set all of "ZCD_NV_EX_TCLK_TABLE" as hot-NV-item, and the "AF_DataRequest" with "AF_EN_SECURITY" can execute more fast.

  • Hello Aries,

    Is there a question here, or are you only providing feedback on the reduced latency from using hot NV items?

    Regards,
    Ryan

  • // these code add into nvocmp.c and nvocmp.h
    
    #define   NVOCMP_HOT_IDS_ARRAY    { \
              {NVOCMP_CMPRID(NVINTF_SYSID_ZSTACK,ZCD_NV_EX_LEGACY,ZCD_NV_NWKKEY), false, 0xFF, 0xFFFF}, \
              {NVOCMP_CMPRID(NVINTF_SYSID_ZSTACK,ZCD_NV_EX_LEGACY,ZCD_NV_NWK_ACTIVE_KEY_INFO), false, 0xFF, 0xFFFF}, \
              {NVOCMP_CMPRID(NVINTF_SYSID_ZSTACK,ZCD_NV_EX_LEGACY,ZCD_NV_NWK_ALTERN_KEY_INFO), false, 0xFF, 0xFFFF}, \
              {NVOCMP_CMPRID(NVINTF_SYSID_ZSTACK,ZCD_NV_EX_LEGACY,ZCD_NV_TCLK_SEED), false, 0xFF, 0xFFFF}, \
               }
               
    typedef struct
    {
      bool     vail;
      uint8_t  pg;
      uint16_t ofs;
    }
    NVOCMP_hotNv_t;
    
    NVOCMP_hotId_t NVOCMP_hotIdArray[] = NVOCMP_HOT_IDS_ARRAY;
    
    NVOCMP_hotNv_t* (*pfn_nvocmp_hotItemMatch)(NVOCMP_hotItem_t hotItem) = NULL;
    void (*pfn_nvocmp_hotItemUpdate)(uint8_t pg, uint16_t ofs, NVOCMP_hotItem_t hotItem) = NULL;
    NVOCMP_hotNv_t* (*pfn_nvocmp_hotItemMatchCont)(uint8_t sysid, uint16_t itemid, void *cBuf, uint16_t clength, uint16_t coff) = NULL;
    void (*pfn_nvocmp_hotItemUpdateCont)(NVOCMP_hotItem_t hotItem, void *cBuf, uint16_t clength, uint16_t coff) = NULL;
    
    static int8_t NVOCMP_findItem(NVOCMP_nvHandle_t *pNvHandle, uint8_t pg, uint16_t ofs,
                                  NVOCMP_itemHdr_t *pHdr, int8_t flag, NVOCMP_itemInfo_t *pInfo)
    {
        bool found = false;
        uint8_t p;
        uint16_t items = 0;
        uint16_t nvSearched = 0;
    #ifdef NVOCMP_GPRAM
        uint32_t vm;
        uint8_t *pTBuffer = RAM_BUFFER_ADDRESS;
    #else
        uint8_t *pTBuffer = (uint8_t *)tBuffer;
    #endif
    
    #ifdef NVOCMP_GPRAM
        NVOCMP_disableCache(&vm);
    #endif
        uint32_t cid = NVOCMP_CMPRID(pHdr->sysid,pHdr->itemid,pHdr->subid);
        // find hot id first, luoyiming 2020-05-21
        if( (flag & NVOCMP_FINDLMASK) == NVOCMP_FINDSTRICT )
        {
          NVOCMP_hotItem_t hotItem = {.subid = pHdr->subid, .itemid = pHdr->itemid, .sysid = pHdr->sysid};
          hotItem.cmpid = cid;
          NVOCMP_hotNv_t* pHotNv = NVOCMP_hotItemMatch(hotItem);
          if( pHotNv )
          {
            NVOCMP_itemHdr_t iHdr;
            NVOCMP_readHeader(pHotNv->pg, pHotNv->ofs, &iHdr, false);
            if((iHdr.stats & NVOCMP_ACTIVEIDBIT) &&
              !(iHdr.stats & NVOCMP_VALIDIDBIT))
            {
              if( iHdr.cmpid == cid )
              {
                memcpy(pHdr, &iHdr, sizeof(NVOCMP_itemHdr_t));
    #ifdef NVOCMP_GPRAM
                NVOCMP_restoreCache(vm);
    #endif
                return(NVINTF_SUCCESS);
              }
            }
          }
        }
        else if((pInfo) && ((flag & NVOCMP_FINDHMASK) == NVOCMP_FINDCONTENT))
        {
          if( pHdr->subid == 0 )
          {
            NVOCMP_itemHdr_t iHdr;
            if(true == NVOCMP_hotItemMatchCont(pHdr->sysid, pHdr->itemid, pInfo, &iHdr))
            {
              if(!NVOCMP_readItem(&iHdr, 0, pInfo->rlength, pInfo->rBuf, false))
              {
                if(!memcmp((uint8_t *)pInfo->rBuf + pInfo->coff, pInfo->cBuf, pInfo->clength))
                {
                  memcpy(pHdr, &iHdr, sizeof(NVOCMP_itemHdr_t));
    #ifdef NVOCMP_GPRAM
                  NVOCMP_restoreCache(vm);
    #endif
                  return(NVINTF_SUCCESS);
                }
              }
            }
          }
        }
    .....
    
    }
    
    
    static void NVOCMP_writeItem(NVOCMP_nvHandle_t *pNvHandle, NVOCMP_itemHdr_t *pHdr,
                                 uint8_t dstPg, uint16_t dstOff, uint8_t *pBuf)
    {
        uint16_t iLen;
        NVOCMP_pageHdr_t pageHdr;
    
        NVOCMP_read(dstPg, NVOCMP_PGHDROFS, (uint8_t *)&pageHdr, NVOCMP_PGHDRLEN);
        if(pageHdr.state == NVOCMP_PGRDY)
        {
          NVOCMP_changePageState(pNvHandle, dstPg, NVOCMP_PGACT);
        }
    
        if(pageHdr.state != NVOCMP_PGACT)
        {
          NVOCMP_failW = NVINTF_FAILURE;
          return;
        }
    
        NVOCMP_ALERT(pageHdr.state == NVOCMP_PGACT, "Something wrong.")
    
        // Total length of this item
        iLen = NVOCMP_ITEMHDRLEN + pHdr->len;
    
        if((dstOff + iLen) <= FLASH_PAGE_SIZE)
        {
            cmpIH_t cHdr;
            uint16_t hOfs, dLen;
            uint8_t newCRC;
    
            // Compressed item header information <-- Lower Addr    Higher Addr-->
            // Byte: [0]      [1]      [2]      [3]      [4]      [5]      [6]
            // Item: SSSSSSII IIIIIIII SSSSSSSS SSLLLLLL LLLLLLCC CCCCCCAV SSSSSSSS
            // LSB of field:         ^           ^            ^        ^          ^
    #if NVOCMP_HDRLE
            cHdr[0] = (pHdr->sysid & 0x3F) | ((pHdr->itemid & 0x3) << 6);
            cHdr[1] = (pHdr->itemid >> 2) & 0xFF;
            cHdr[2] = pHdr->subid & 0xFF;
            cHdr[3] = ((pHdr->subid >> 8) & 0x3) | ((pHdr->len & 0x3F) << 2);
            cHdr[4] = (pHdr->len >> 6) & 0x3F;
    #else
            cHdr[0] = ((pHdr->sysid << 2) | ((pHdr->itemid >> 8) & 0x3));
            cHdr[1] = (pHdr->itemid & 0xFF);
            cHdr[2] = ((pHdr->subid >> 2) & 0xFF);
            cHdr[3] = ((pHdr->subid & 0x3) << 6) | ((pHdr->len >> 6) & 0x3F);
            cHdr[4] = ((pHdr->len & 0x3F) << 2);
    #endif
            // Header is located after the item data
            dLen = pHdr->len;
            hOfs = dstOff + dLen;
    
            // update hot ids, luoyiming 2020-05-22
            NVOCMP_hotItem_t hotItem = {.subid = pHdr->subid, .itemid = pHdr->itemid, .sysid = pHdr->sysid};
            hotItem.cmpid = pHdr->cmpid;
            NVOCMP_hotItemUpdate(dstPg, dstOff, hotItem);
    
            // update cont hot id, luoyiming 2021-11-29
            NVOCMP_hotItemUpdateCont(hotItem, pBuf, pHdr->len, 0);
    
            if (iLen <= NVOCMP_SMALLITEM)
            {
                // Construct item in one buffer
                // Put data into buffer
                memcpy(NVOCMP_itemBuffer, (const void *)pBuf, dLen);
                // Put most of header into buffer
                memcpy(NVOCMP_itemBuffer + dLen, (const void *)cHdr,
                       NVOCMP_HDRCRCINC);
                // Calculate CRC
                newCRC = NVOCMP_doRAMCRC(NVOCMP_itemBuffer, dLen +
                                         NVOCMP_HDRCRCINC, 0);
    #if NVOCMP_HDRLE
                // Insert CRC and last bytes
                cHdr[4] |= ((newCRC & 0x3) << 6);
                // Note NVOCMP_VALIDIDBIT set implicitly zero
                cHdr[5] = ((newCRC >> 2) & 0x3F) | (NVOCMP_ACTIVEIDBIT << 6);
    #else
                // Insert CRC and last bytes
                cHdr[4] |= ((newCRC >> 6) & 0x3);
                // Note NVOCMP_VALIDIDBIT set implicitly zero
                cHdr[5] = ((newCRC & 0x3F) << 2) | NVOCMP_ACTIVEIDBIT;
    #endif
                cHdr[6] = NVOCMP_SIGNATURE;
                memcpy(NVOCMP_itemBuffer + dLen, (const void *)cHdr,
                       NVOCMP_ITEMHDRLEN);
                // NVS_write
                NVOCMP_failW = NVOCMP_write(dstPg, dstOff,
                                            NVOCMP_itemBuffer, iLen);
                // Advance to next location
                dstOff += iLen;
                pNvHandle->actOffset += iLen;
                pNvHandle->pageInfo[dstPg].offset = dstOff;
            }
            else
            {
                // Write header/item separately
                // Calculate CRC on data portion
                newCRC = NVOCMP_doRAMCRC(pBuf, dLen, 0);
                // Finish CRC using header portion
                newCRC = NVOCMP_doRAMCRC(cHdr, NVOCMP_HDRCRCINC, newCRC);
                // Complete Header with CRC, bits, and sig
    #if NVOCMP_HDRLE
                // Insert CRC and last bytes
                cHdr[4] |= ((newCRC & 0x3) << 6);
                // Note NVOCMP_VALIDIDBIT set implicitly zero
                cHdr[5] = ((newCRC >> 2) & 0x3F) | (NVOCMP_ACTIVEIDBIT << 6);
    #else
                // Insert CRC and last bytes
                cHdr[4] |= ((newCRC >> 6) & 0x3);
                // Note NVOCMP_VALIDIDBIT set implicitly zero
                cHdr[5] = ((newCRC & 0x3F) << 2) | NVOCMP_ACTIVEIDBIT;
    #endif
                cHdr[6] = NVOCMP_SIGNATURE;
                // Write data
                NVOCMP_failW = NVOCMP_write(dstPg, dstOff, pBuf, dLen);
                // Write header
                NVOCMP_failW |= NVOCMP_write(dstPg, hOfs, cHdr, NVOCMP_ITEMHDRLEN);
                // Advance to next location
                NVOCMP_ASSERT(dstOff < (dstOff + iLen), "Page offset overflow!")
                if(!NVOCMP_failW)
                {
                    dstOff += iLen;
                    pNvHandle->actOffset += iLen;
                    pNvHandle->pageInfo[dstPg].offset = dstOff;
                }
                else
                {
                    return;
                }
            }
            // If there was a write failure, delete item
            NVOCMP_ALERT(!NVOCMP_failW, "Driver write failure. Item deleted.")
            if (NVOCMP_failW)
            {
                NVOCMP_setItemInactive(pNvHandle, dstPg, hOfs);
            }
        }
        else
        {
            // Not enough room on page
            NVOCMP_failW = NVINTF_BADLENGTH;
        }
    }
    
    /*********************************************************************
     * @fn      hotItemMatch
     *
     * @brief   Look for the parameter 'id' in the hot items array.
     *
     * @param   id - A valid NV item Id.
     *
     * @return  A valid index into the hot items if the item is hot; OSAL_NV_MAX_HOT if not.
     */
    static NVOCMP_hotNv_t* NVOCMP_hotItemMatch(NVOCMP_hotItem_t hotItem)
    {
      uint8_t nvNum = sizeof(NVOCMP_hotIdArray)/sizeof(NVOCMP_hotId_t);
      uint8_t n;
      for ( n=0; n<nvNum; n++ )
      {
        if( (hotItem.cmpid == NVOCMP_hotIdArray[n].cid) && (NVOCMP_hotIdArray[n].nv.vail == true) )
        {
          return &NVOCMP_hotIdArray[n].nv;
        }
      }
    
      if( pfn_nvocmp_hotItemMatch )
      {
        return pfn_nvocmp_hotItemMatch(hotItem);
      }
      return NULL;
    }
    
    /*********************************************************************
     * @fn      hotItemUpdate
     *
     * @brief   If the parameter 'id' is a hot item, update the corresponding hot item data.
     *
     * @param   pg - The new NV page corresponding to the hot item.
     * @param   off - The new NV page offset corresponding to the hot item.
     * @param   id - A valid NV item Id.
     *
     * @return  none
     */
    static void NVOCMP_hotItemUpdate(uint8_t pg, uint16_t ofs, NVOCMP_hotItem_t hotItem)
    {
      uint8_t nvNum = sizeof(NVOCMP_hotIdArray)/sizeof(NVOCMP_hotId_t);
      uint8_t n;
      for ( n=0; n<nvNum; n++ )
      {
        if( hotItem.cmpid == NVOCMP_hotIdArray[n].cid )
        {
          NVOCMP_hotIdArray[n].nv.pg = pg;
          NVOCMP_hotIdArray[n].nv.ofs = ofs;
          NVOCMP_hotIdArray[n].nv.vail = true;
          return;
        }
      }
    
      if( pfn_nvocmp_hotItemUpdate )
      {
        pfn_nvocmp_hotItemUpdate(pg, ofs, hotItem);
      }
    }
    
    static bool NVOCMP_hotItemMatchCont(uint8_t sysid, uint16_t itemid, NVOCMP_itemInfo_t *pInfo, NVOCMP_itemHdr_t* pHdr)
    {
      NVOCMP_hotNv_t* hotNv = NULL;
      if( pfn_nvocmp_hotItemMatchCont )
      {
        hotNv = pfn_nvocmp_hotItemMatchCont(sysid, itemid, pInfo->cBuf, pInfo->clength, pInfo->coff);
        if( hotNv )
        {
          NVOCMP_readHeader(hotNv->pg, hotNv->ofs, pHdr, false);
          if((pHdr->stats & NVOCMP_ACTIVEIDBIT) && !(pHdr->stats & NVOCMP_VALIDIDBIT))
          {
            if((pHdr->sysid == sysid) && (pHdr->itemid == itemid))
            {
              return true;
            }
          }
        }
      }
      return false;
    }
    
    static void NVOCMP_hotItemUpdateCont(NVOCMP_hotItem_t hotItem, void *cBuf, uint16_t clength, uint16_t coff)
    {
      if( pfn_nvocmp_hotItemUpdateCont )
      {
        pfn_nvocmp_hotItemUpdateCont(hotItem, cBuf, clength, coff);
      }
    }
    
    // this code add in application code
    
    typedef struct
    {
      uint8_t    ieee[8];
      uint16_t   clength;
      NVOCMP_hotNv_t nv;
    }mfgHotNv_t;
    
    mfgHotNv_t mfgApsKeyNvHotIdBuf[ZDSECMGR_TC_DEVICE_MAX] = {0};
    
    NVOCMP_hotNv_t* MFG_NvHotIdMatch(NVOCMP_hotItem_t hotItem)
    {
      if( hotItem.sysid == NVINTF_SYSID_ZSTACK && hotItem.itemid == ZCD_NV_EX_TCLK_TABLE )
      {
        if( hotItem.subid < ZDSECMGR_TC_DEVICE_MAX )
        {
          if(false == mfgApsKeyNvHotIdBuf[hotItem.subid].nv.vail)
          {
            return NULL;
          }
          return &mfgApsKeyNvHotIdBuf[hotItem.subid].nv;
        }
      }
      return NULL;
    }
    
    void MFG_NvHotIdUpdate(uint8_t pg, uint16_t ofs, NVOCMP_hotItem_t hotItem)
    {
      if( (hotItem.sysid == NVINTF_SYSID_ZSTACK) && (hotItem.itemid == ZCD_NV_EX_TCLK_TABLE) )
      {
        if( hotItem.subid < ZDSECMGR_TC_DEVICE_MAX )
        {
          mfgApsKeyNvHotIdBuf[hotItem.subid].nv.vail = true;
          mfgApsKeyNvHotIdBuf[hotItem.subid].nv.ofs = ofs;
          mfgApsKeyNvHotIdBuf[hotItem.subid].nv.pg = pg;
        }
      }
    }
    
    NVOCMP_hotNv_t* MFG_NvHotIdMatchCont(uint8_t sysid, uint16_t itemid, void *cBuf, uint16_t clength, uint16_t coff)
    {
      if( sysid == NVINTF_SYSID_ZSTACK && itemid == ZCD_NV_EX_TCLK_TABLE )
      {
        uint8_t n;
        for(n = 0; n <ZDSECMGR_TC_DEVICE_MAX; n++)
        {
          uint8_t idx = (ZDSECMGR_TC_DEVICE_MAX - 1) - n;
          if(mfgApsKeyNvHotIdBuf[idx].clength == clength)
          {
            if(!memcmp(mfgApsKeyNvHotIdBuf[idx].ieee, cBuf, 8))
            {
              return &mfgApsKeyNvHotIdBuf[idx].nv;
            }
          }
        }
      }
      return NULL;
    }
    
    void MFG_NvHotIdUpdateCont(NVOCMP_hotItem_t hotItem, void *cBuf, uint16_t clength, uint16_t coff)
    {
      if( (hotItem.sysid == NVINTF_SYSID_ZSTACK) && (hotItem.itemid == ZCD_NV_EX_TCLK_TABLE) )
      {
        if( hotItem.subid < ZDSECMGR_TC_DEVICE_MAX )
        {
          if((coff == 8) && (clength == 8))
          {
            mfgApsKeyNvHotIdBuf[hotItem.subid].clength = clength;
            memcpy(mfgApsKeyNvHotIdBuf[hotItem.subid].ieee, cBuf, 8);
          }
          else if((coff == 0) && (mfgApsKeyNvHotIdBuf[hotItem.subid].clength == 8))
          {
            memcpy(mfgApsKeyNvHotIdBuf[hotItem.subid].ieee, cBuf + 8, 8);
          }
        }
      }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

  • When add Hot-NV item. latency of "AF_DataRequest" reduce from 5ms to 1ms, "APSME_SearchTCLinkKeyEntry" from 20ms to 3.5ms