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.

WEBENCH® Tools/CC2652R: Issue: Group-ID could be stored only 1-record in NV-RAM

Part Number: CC2652R

Tool/software: WEBENCH® Design Tools

condition: APS_MAX_GROUPS=16

Processing:

1,use Zstackapi_ApsAddGroupReq to add many group-IDs (less than 16) into group table.

2,use Zstackapi_ApsFindAllGroupsReq to lookup added group-IDs, all the group-IDs just be added is appearing in parameter "rsp.pGroupList".

3,restart this CC2652R zigbee device. And then use Zstackapi_ApsFindAllGroupsReq to lookup added group-IDs, only one group-IDs is appearing.

Some clue of this issue:

I have tried to debug the function "osal_nv_write" when NV-id is "ZCD_NV_GROUP_TABLE". I have tried to print out the value of NV-buffer. Index 4, 24, 44, 64 and 84 is the value of Group-ID. But all of them are same with the Gourp-ID that is the first added into Group-Table. 

  • I have uploaded the data of ZCD_NV_GROUP_TABLE and the data of apsGroupTable. It seems that the endpoint value is stored correctly but the group-ID is stored un-correctly.

    Watch2.zip

  • Hi,

    Is this on the 3.20 SDK?

    Regards,
    Toby

  • Yes, it is on the 3.20 SDK.  I have test this issue on 3.10 SDK, it still could not stored group-ID.

  • Can you be sure that is it a issue?

  • Yes, I was able to reproduce this issue.

    It will be fixed in the future.

  • Don't say "in the future", Uchiha Obito. It is a very important issue. you had better to give some patch to fix it.

  • Apologies, I was unaware of the importance of this issue; thank you for highlighting it.

    As the 3.30 SDK has been released when this issue was found, the issue will be formally fixed in a 3.30+ SDK.

    In the meantime, the following modifications may be used to fix the issue:

    In osal_nv.c:

    /******************************************************************************
     * @fn      osal_nv_write
     *
     * @brief   Write a data item to NV. Function can write an entire item to NV or
     *          an element of an item by indexing into the item with an offset.
     *
     * @param   id  - Valid NV item Id.
     * @param   ndx - Index offset into item
     * @param   len - Length of data to write.
     * @param  *buf - Data to write.
     *
     * @return  SUCCESS if successful, NV_ITEM_UNINIT if item did not
     *          exist in NV and offset is non-zero, NV_OPER_FAILED if failure.
     */
    uint8 osal_nv_write( uint16 id, uint16 ndx, uint16 len, void *buf )
    {
        // toby added
        #include "aps_groups.h"
    
        extern uint8_t restoreInProgress_NLME;
        extern apsGroupItem_t *apsGroupTable;
        struct apsGroupNVItem {
            uint8_t                endpoint;
            aps_Group_t          group;
        };
    
        apsGroupItem_t *pLoop = apsGroupTable;
        struct apsGroupNVItem item;
    
        if (id == ZCD_NV_GROUP_TABLE)
        {
            if (restoreInProgress_NLME)
                return; // don't write to NV group table while a restore is in progress
    
            // write correctly to NV group table
            uint16_t i = 0;
            while ( pLoop )
            {
              // Build the record
              item.endpoint = pLoop->endpoint;
              OsalPort_memcpy( &(item.group), &(pLoop->group), sizeof ( aps_Group_t ) );
    
              OsalPort_memcpy(buf + (uint16_t)((sizeof(uint16_t)) + (i * sizeof ( struct apsGroupNVItem ))),  &item, sizeof ( struct apsGroupNVItem ));
    
              pLoop = pLoop->next;
              i += 1;
            }
        }
        // end added
    
      // Legacy items use ZCD_NV_EX_LEGACY as the ID and the id as the sub-id.
      return ( osal_nv_write_ex( ZCD_NV_EX_LEGACY, id, ndx, len, buf ) );
    }

    In zd_app.c:

    #if defined ( NV_RESTORE )
    /*********************************************************************
     * @fn      ZDApp_RestoreNetworkState()
     *
     * @brief   This function will restore the network state of the
     *          device if the network state is stored in NV.
     *
     * @param   none
     *
     * @return
     *    ZDO_INITDEV_RESTORED_NETWORK_STATE  - The device's network state was
     *          restored.
     *    ZDO_INITDEV_NEW_NETWORK_STATE - The network state was not used.
     *          This could mean that zgStartupOption said to not restore, or
     *          it could mean that there was no network state to restore.
     *
     */
    
    uint8_t restoreInProgress_NLME = FALSE; // toby added
    uint8_t ZDApp_RestoreNetworkState( void )
    {
      uint8_t nvStat;
    
      // Initialize NWK NV items
      nvStat = NLME_InitNV();
    
      if ( nvStat == SUCCESS )
      {
          restoreInProgress_NLME = TRUE; // toby added
    
        if ( NLME_RestoreFromNV() )
        {
          // Are we a coordinator
          ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
          if ( ZDAppNwkAddr.addr.shortAddr == 0 )
          {
            ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
          }
          if(ZG_DEVICE_ENDDEVICE_TYPE)
          {
            devStartMode = MODE_REJOIN;
            _NIB.nwkState = NWK_INIT;
          }
          else
          {
            devStartMode = MODE_RESUME;
          }
          osal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );
        }
        else
          nvStat = NV_ITEM_UNINIT;
    
        restoreInProgress_NLME = FALSE; // toby added
    
    
        nwkFrameCounterChanges = 0;
    
        if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
        {
          ZDApp_RestoreNwkKey( TRUE );
        }
    
        // The default for RxOnWhenIdle is true for Routers and false for end devices
        // [setup in the NLME_RestoreFromNV()].  Change it here if you want something
        // other than default.
      }
    
      if ( nvStat == ZSUCCESS )
        return ( ZDO_INITDEV_RESTORED_NETWORK_STATE );
      else
        return ( ZDO_INITDEV_NEW_NETWORK_STATE );
    }
    #endif // NV_RESTORE

    Let us know if this works for you.