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.

[FAQ] CC2538: Z-Stack 3.0.2 Known Issues and Fixes

Part Number: CC2538
Other Parts Discussed in Thread: CC2531, CC2530, Z-STACK, , CC2592

This page contains known issues on the published Zigbee Software releases from TI. TI has a software release candidates and all fixes may not be available to developers as soon as they are implemented. The purpose of this page is to provide developers information of the issues and fixes in case an issue is found on the published software before a new release is made. This will help developers fix problems before they are fixed in released Zigbee releases from TI.

1. Memory Leak in zcl.c

Issue description:
Memory leak in zcl_HandleExternal()

Proposed Fix:

zcl_HandleExternal()
{
...
#ifdef BDB_REPORTING
    if(pCmd->zclHdr.commandID == ZCL_CMD_CONFIG_REPORT)
    {
      bdb_ProcessInConfigReportCmd(pCmd);
      osal_msg_deallocate((uint8 *)pCmd); // ++++++++++++++ ADD THIS CODE
      return TRUE;          
    }
    if(pCmd->zclHdr.commandID == ZCL_CMD_READ_REPORT_CFG)
    {
      bdb_ProcessInReadReportCfgCmd(pCmd);
      osal_msg_deallocate((uint8 *)pCmd); // ++++++++++++++ ADD THIS CODE
      return TRUE;
    }
#endif
...
}

2. Network association issues after prior APS Remove or Leave Request

Issue description:
Under some conditions when an APS Remove/Leave Request is sent to a device to remove itself or another device, NV will not be cleared properly and new network associates will not work due to the old APS key from the TC Link Key exchange staying persistent in NV.

Proposed Fix:

// in ZDApp.c
UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
...
  if ( events & ZDO_DEVICE_RESET )
  {
#ifdef ZBA_FALLBACK_NWKKEY
    if ( devState == DEV_END_DEVICE_UNAUTH )
    {
      ZDSecMgrFallbackNwkKey();
    }
    else
#endif
    {
      // Set the NV startup option to force a "new" join.
      zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE | ZCD_STARTOPT_DEFAULT_CONFIG_STATE ); /// ++++ MODIFY THIS LINE ++++

      // The device has been in the UNAUTH state, so reset
      // Note: there will be no return from this call
      SystemResetSoft();
    }
  }
...
}

3. Soft Reset/Freezing/Stack Overflow due to BDB_REPORTING on CC2530/CC2531

Issue description:
The default size of the XDATA stack is 0x300 (768 bytes), and with the addition of BDB_REPORTING in an application, sometimes the callstack will become too large and overflow the XDATA stack.

Proposed Fix:
Increase the size of the XDATA stack in the project options to at least 0x400:

4. OTA Upgrade from ZHA 1.2 to Z3.0 results in broken device

Issue description:
When doing an OTA upgrade from ZHA 1.2 to Z3.0, the usage of some NV items have changed between versions and the network security information is formatted in a different way. Because of this, it is necessary that we "upgrade" some NV security items when doing this upgrade.

Proposed Fix:

Some code below already exists in Z-Stack and is provided as context. Add all the code changes for this fix are under the compile flag UPGRADE_SECURITY_NV_ITEMS

// in ZGlobals.c


/*********************************************************************
 * LOCAL FUNCTIONS
 */
...
#ifdef UPGRADE_SECURITY_NV_ITEMS
static void zgUpgradeSecurityNVItems( void );
#endif // UPGRADE_SECURITY_NV_ITEMS
...

uint8 zgInit( void )
{
...
#ifndef NONWK
  if ( ZG_SECURE_ENABLED )
  {
    // Initialize the Pre-Configured Key to the default key
    zgPreconfigKeyInit( setDefault );

    // Initialize NV items for all Keys: NWK, APS, TCLK and Master
    ZDSecMgrInitNVKeyTables( setDefault );
  }
#endif // NONWK

#ifdef UPGRADE_SECURITY_NV_ITEMS
  zgUpgradeSecurityNVItems();
#endif // UPGRADE_SECURITY_NV_ITEMS

  // Clear the Config State default
  if ( setDefault )
  {
    zgWriteStartupOptions( ZG_STARTUP_CLEAR, ZCD_STARTOPT_DEFAULT_CONFIG_STATE );
  }
...
}

#ifdef UPGRADE_SECURITY_NV_ITEMS
static void zgUpgradeSecurityNVItems( void )
{
  //Nv configuration to allow upgrade from HA1.2 to Z3.0

  uint8 isOnANetwork = 1;
  //Read bdb attribute
  if(osal_nv_read(ZCD_NV_BDBNODEISONANETWORK, 0, sizeof(uint8), &isOnANetwork) == SUCCESS)
  {
    //After upgrade, this parameter will be 0, then update properly as it is in a network.
    //If the device was not in a network and is upgraded, the BDB will handle the network 
    //configuration status and will performing FN reset.
    
    nwkSecMaterialDesc_t  nwkSecMaterialDesc;
    nwkActiveKeyItems     keyItems;
    uint8                 keyAttributes;
    uint8                 tempKey[SEC_KEY_LEN];
    
    osal_memset(tempKey, 0x00, SEC_KEY_LEN);
    
    //Get the network frame counter from old NV item, also check if old key exists.
    //if it doesn't, we can assume that this is factory new Z3.0 device instead of 
    //upgraded ZHA 1.2 device
    osal_nv_read( ZCD_NV_NWKKEY, 0, sizeof( nwkActiveKeyItems ),(void *)&keyItems );
    
    if( osal_memcmp(tempKey, keyItems.active.key, SEC_KEY_LEN) )
    {
      // device is factory new, don't do anything 
    }
    // else if node is not on a network currently and is not factory new Z3.0 device, 
    // it must be ZHA 1.2 -> Z3.0.1 upgraded device
    else if(!isOnANetwork)
    {
      //If none of these parameters can be configured by Nv operations BDB will be able to initialize or handle.
      
      //set bdbNodeIsOnANetwork attribute to 1 indicating that we need to resume our network state
      isOnANetwork = 0x01;
      osal_nv_write( ZCD_NV_BDBNODEISONANETWORK, 0, sizeof(uint8), &isOnANetwork );
      
      //Set the network frame counter in new NV item, frame counter will be incremented by 1000+250 in ZDApp_RestoreNwkSecMaterial() 
      //to ensure that its outgoing packets can be used by devices in its previous network
      nwkSecMaterialDesc.FrameCounter = keyItems.frameCounter; 
      
      //Retrieve Extended PANID from NIB in NV
      osal_nv_read( ZCD_NV_NIB, osal_offsetof(nwkIB_t,extendedPANID), Z_EXTADDR_LEN, &nwkSecMaterialDesc.extendedPanID );
      
      //Set the BDB network security material, BDB state machine will restore network state if this is a valid entry
      osal_nv_write( ZCD_NV_NWK_SEC_MATERIAL_TABLE_START, 0, sizeof(nwkSecMaterialDesc_t), &nwkSecMaterialDesc );  
      
      //indicate to BDB that our previous nwk was non-R21, so don't expect TC Link Key exchange
      keyAttributes = ZG_NON_R21_NWK_JOINED;
      osal_nv_write(ZCD_NV_TCLK_TABLE_START, osal_offsetof(APSME_TCLKDevEntry_t,keyAttributes), sizeof(uint8), &keyAttributes); 
    }
  }
}
#endif // UPGRADE_SECURITY_NV_ITEMS

5. IEEE Address of CC2538ZNP is reported incorrectly

Issue description:
MSB and LSB of IEEE address are flipped when using the CC2538ZNP project. This is due to the placement of the IEEE address in Flash changing between test and production versions of the CC2538 SoC devices. Non-ZNP CC2538ZNP projects are not affected because they use a different ZMain.c file, which already has the fix for this applied.

Proposed Fix:

// in ZMain.c for CC2538ZNP

/******************************************************************************
 * LOCAL DEFINITIONS
 */

// TI IEEE Organizational Unique Identifier
#define IEEE_OUI 0x00124B

...

// replace zmain_ext_addr() with the definition below
static void zmain_ext_addr( void )
{
  uint8 nullAddr[Z_EXTADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  uint8 writeNV = TRUE;

  // First check whether a non-erased extended address exists in the OSAL NV.
  if ((SUCCESS != osal_nv_item_init(ZCD_NV_EXTADDR, Z_EXTADDR_LEN, NULL))  ||
      (SUCCESS != osal_nv_read(ZCD_NV_EXTADDR, 0, Z_EXTADDR_LEN, aExtendedAddress)) ||
      (osal_memcmp(aExtendedAddress, nullAddr, Z_EXTADDR_LEN)))
  {
    // Attempt to read the extended address from the location in the last flash
    // page where the commissioning tools know to reserve it.
    if (!osal_memcmp((uint8 *)HAL_FLASH_IEEE_ADDR, nullAddr, Z_EXTADDR_LEN))
    {
      (void)osal_memcpy(aExtendedAddress, (uint8 *)HAL_FLASH_IEEE_ADDR, Z_EXTADDR_LEN);
    }
    else
    {
      // Disable prefetch when reading from Information Page.
      uint32 fctl = HWREG(FLASH_CTRL_FCTL);
      HWREG(FLASH_CTRL_FCTL) = fctl & ~(FLASH_CTRL_FCTL_PREFETCH_ENABLE);

      // Copy 64-bit extended address from the Information Page
      (void)osal_memcpy(aExtendedAddress, (uint8*)HAL_INFO_IEEE_ADDR, Z_EXTADDR_LEN);
      if (!osal_memcmp(aExtendedAddress, nullAddr, Z_EXTADDR_LEN))
      {
        uint32 oui = IEEE_OUI;
        // IEEE OUI is located in the upper 3 bytes of an 8-byte extended address
        // Early Test CC2538EMs had the TI OUI located in the 2nd word,
        // Production CC2538 devices have the TI OUI located in the 1st word
        if (osal_memcmp(&aExtendedAddress[1], &oui, 3))
        {
          // OUI found in 1st word, swap words to place OUI in upper bytes
          (void)osal_memcpy(aExtendedAddress, &aExtendedAddress[4], Z_EXTADDR_LEN/2);
          (void)osal_memcpy(&aExtendedAddress[4], (uint8*)HAL_INFO_IEEE_ADDR, Z_EXTADDR_LEN/2);
        }
      }
      else  // No valid extended address was found.
      {
        uint8 idx;

#if !defined ( NV_RESTORE )
        writeNV = FALSE;  // Make a temporary IEEE address, not saved in NV
#endif

       /* Create a sufficiently random extended address for expediency.
        * Note: this is only valid/legal in a test environment and
        *       must never be used for a commercial product.
        */
        for (idx = 0; idx < (Z_EXTADDR_LEN - 2);)
        {
          uint16 randy = osal_rand();
          aExtendedAddress[idx++] = LO_UINT16(randy);
          aExtendedAddress[idx++] = HI_UINT16(randy);
        }
        // Next-to-MSB identifies ZigBee device type.
#if ZG_BUILD_COORDINATOR_TYPE && !ZG_BUILD_JOINING_TYPE
        aExtendedAddress[idx++] = 0x10;
#elif ZG_BUILD_RTRONLY_TYPE
        aExtendedAddress[idx++] = 0x20;
#else
      aExtendedAddress[idx++] = 0x30;
#endif
      // MSB has historical signficance.
        aExtendedAddress[idx] = 0xF8;
      }

      // Restore flash control to previous state
      HWREG(FLASH_CTRL_FCTL) = fctl;
    }

    if (writeNV)
    {
      (void)osal_nv_write(ZCD_NV_EXTADDR, 0, Z_EXTADDR_LEN, aExtendedAddress);
    }
  }

  // Set the MAC PIB extended address according to results from above.
  (void)ZMacSetReq(MAC_EXTENDED_ADDRESS, aExtendedAddress);
}

...

6. Modifying CC2538 Linker to utilize all 32k RAM causes lockup

Issue description:
Some CC2538 parts have 32k of RAM, but the first 16k is disabled by default in our linker file since only the second 16k is retained in all power modes. The first 16k of RAM loses its contents when the device enters PM2. If you are designing a device which never goes into low power mode, it is fine to reclaim this RAM for application usage. You can do this by changing the following in the linker file:

//
// Define a region for the on-chip SRAM.
//
define region SRAM = mem:[from 0x20000000 to 0x20007FFF]; // 0x20004000 --> 0x20000000

However, in some applications, increasing the RAM to this value will cause Z-Stack to lock up.


Proposed Fix:

Move the run-time stack to the end of RAM. Find the code below in your linker file and make the following change:

//
// Indicate that the noinit values should be left alone.  This includes the
// stack, which if initialized will destroy the return address from the
// initialization code, causing the processor to branch to zero and fault.
//
do not initialize { section .noinit };
place at end of SRAM { section .noinit }; // ++++++++++ ADD THIS LINE ++++++++++

7. ZED does not receive Broadcast sent to MAC dst 0xFFFF from parent

Issue description:
In Zigbee, if a broadcast message is sent to destination address 0xFFFF, all devices (Rx-always-on AND sleepy) will receive this message. This means that parent routing devices must buffer broadcasts sent to 0xFFFF for any of their sleepy ZED children. In Z-Stack, if you have a single ZR/ZC node that has more than (32 - MAX_NEIGHBOR_ENTRIES) direct sleepy ZED children, each ZED beyond this number will not be able to receive the broadcast message. MAX_NEIGHBOR_ENTRIES is 16 by default for routing devices in Z-Stack.

Proposed Fix:
There is no perfect fix available for this right now since this implementation is in the pre-compiled Z-Stack libraries, but there are some workarounds we can suggest:

  1. Do not send broadcast messages to destination 0xFFFF, only use 0xFFFC/0xFFFD (MAC dst addr for rx-always-on devices only) and send unicast messages to sleepy ZED nodes.
    • This is the preferred method, since you will not have to limit your device table size as a result.
  2. Limit the number of sleepy ZED nodes per ZC/ZR to a maximum of 16
    • This is good practice for large networks anyway, for a robust mesh network topology you should always aim for one ZR for every 10-15 ZEDs
  3. Decrease MAX_NEIGHBOR_ENTRIES from 16 to a smaller value
    • Not recommended, MAX_NEIGHBOR_ENTRIES determines the size of your neighbor table, which is a list of ZR devices that are within RF range of you. Larger neighbor table = easier Zigbee route discovery = more robust mesh networking. TI Z-Stack was tested with MAX_NEIGHBOR_ENTRIES=16 to be a good value for most Zigbee networking situations.

8. NWK/APS packet retries/failure when ZED polls during commissioning (Transport Key, Simple Descriptor Request, etc)

Issue description:
Sometimes ZC will fail to send out a NWK/APS layer packet during network commissioning, e.g. Transport Key, to a joining ZED, and this requires the ZED to poll again to get the packet. This will not cause functionality issues for the joining device since it will retry and eventually get the packet, but it is not ideal to need to retry to receive the same packet multiple times. This issue is caused by a race condition involving a blocking NV write operation that happens on the ZC after a new device joins the network.

Proposed Fix:
Change the value of ZDAPP_UPDATE_NWK_NV_TIME from it's default of 700 (ms) to a larger value, like 3500. This will cause the NV write operation to start at a later time and thus not interfere with network commissioning.

9. ZED does not go back to low power state after losing parent and attempting recovery

Issue description:
After the API bdb_ZedAttemptRecoverNwk() is called from the application to attempt for a ZED to rejoin the network, the receiver is not turned back off, which causes ZED to leave RX on during idle and not go into a low power state.

Proposed fix:
Modify the function bdb_parentLost() in bdb.c:

void bdb_parentLost(void)
{
#if ZG_BUILD_ENDDEVICE_TYPE
  if(ZG_DEVICE_ENDDEVICE_TYPE)
  {
    while(pBDBListNwk)
    {
      bdb_nwkDescFree(pBDBListNwk);
    }
    
    nwk_desc_list_free();  
    if(bdbCommissioningProcedureState.bdbCommissioningState != BDB_PARENT_LOST)
    {
      //If parent lost during TCLK exchange, then report TCLK exchange fail
      if(bdbCommissioningProcedureState.bdbCommissioningState == BDB_COMMISSIONING_STATE_TC_LINK_KEY_EXCHANGE)
      {
        bdb_reportCommissioningState(BDB_COMMISSIONING_STATE_TC_LINK_KEY_EXCHANGE, FALSE);
        return;
      }
      bdbCommissioningProcedureState.bdb_ParentLostSavedState = bdbCommissioningProcedureState.bdbCommissioningState;
      
    }
    bdbCommissioningProcedureState.bdbCommissioningState = BDB_PARENT_LOST;
    NLME_OrphanStateSet();
    ZDApp_ChangeState( DEV_NWK_ORPHAN );

    // turn receiver off while in orphan state
    byte temp = FALSE;                   // ++++++++++++++ ADD THIS CODE
    ZMacSetReq(ZMacRxOnIdle, &temp);     // ++++++++++++++ ADD THIS CODE

    bdb_reportCommissioningState(BDB_PARENT_LOST,FALSE);
  }
#endif
}

10. ZCL ID mixup for Chatting + Voice Over Zigbee

Issue description:
ZCL IDs are swapped

Proposed fix:

// this is how it is now

#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_CHATTING           0x0904

#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE  0x0905

// IDs should be swapped like this:

#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_CHATTING           0x0905

#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE  0x0904

11. CC2530/1 ZNP device sporadically returns ZMemError

Issue description:
Sometimes in our Zigbee Linux Gateway solution, a CC2530/1 ZNP device will return a failure message with the status ZMemError, like below.

[14:52:12.119,309] [GATEWAY/LSTN] PKTTYPE: [                  Z_STACK<<<<<<<<<<<GATEWAY         ] afDataReq
[14:52:12.120,400] [GATEWAY/LSTN] PKTBODY:                                                          cmdID = AF_DATA_REQ
[14:52:12.122,748] [GATEWAY/LSTN] PKTBODY:                                                          dstAddr :
[14:52:12.123,831] [GATEWAY/LSTN] PKTBODY:                                                            addrMode = SHORT
[14:52:12.125,632] [GATEWAY/LSTN] PKTBODY:                                                            shortAddr = 0x0000EC56 (60502)
[14:52:12.126,453] [GATEWAY/LSTN] PKTBODY:                                                            endpoint = 0x00000001 (1)
[14:52:12.126,601] [GATEWAY/LSTN] PKTBODY:                                                            panID = 0x00000000 (0)
[14:52:12.128,656] [GATEWAY/LSTN] PKTBODY:                                                          srcEndpoint = 0x00000004 (4)
[14:52:12.128,963] [GATEWAY/LSTN] PKTBODY:                                                          clusterID = 0x00000402 (1026)
[14:52:12.129,108] [GATEWAY/LSTN] PKTBODY:                                                          transID = 0x00000011 (17)
[14:52:12.129,856] [GATEWAY/LSTN] PKTBODY:                                                          options :
[14:52:12.130,114] [GATEWAY/LSTN] PKTBODY:                                                          radius = 0x0000001E (30)
[14:52:12.130,282] [GATEWAY/LSTN] PKTBODY:                                                          payload (hex string) = 00:11:06:00:00:00:29:3C:00:84:03:64:00
[14:52:12.130,864] [Z_STACK/LSTN] PKTTYPE: [         NPISRVR<<Z_STACK                           ] [SREQ] 21:24:02:02:56:EC:00:08:02:10:F3:EE:01:00:00:04:02:04:11:00:1E:0D:00:00:11:06:00:00:00:29:3C:00:84:03:64:00
[14:52:12.131,305] [NPISRVR/MAIN] PKT_HEX: [SOCZIGB<<NPISRVR                                    ] [send] 21:24:02:02:56:EC:00:08:02:10:F3:EE:01:00:00:04:02:04:11:00:1E:0D:00:00:11:06:00:00:00:29:3C:00:84:03:64:00
[14:52:12.145,118] [NPISRVR/U_RX] PKT_HEX: [SOCZIGB>>NPISRVR                                    ] [SRSP] 01:64:02:10
[14:52:12.145,559] [NPISRVR/MAIN] PKT_HEX: [         NPISRVR>>Z_STACK                           ] [ucst] 01:64:02:10
[14:52:12.146,349] [Z_STACK/LSTN] PKTTYPE: [                  Z_STACK>>>>>>>>>>>GATEWAY         ] zstackDefaultRsp
[14:52:12.146,499] [Z_STACK/LSTN] PKTBODY:                                                          cmdID = AF_DATA_REQ
[14:52:12.146,567] [Z_STACK/LSTN] PKTBODY:                                                          status = ZMemError
[14:52:12.148,151] [GATEWAY/LSTN] PKTTYPE: [                                    GATEWAY>>>>>>>>>>>CON007] GwZigbeeGenericCnf
[14:52:12.148,413] [GATEWAY/LSTN] PKTBODY:                                                          cmdId = ZIGBEE_GENERIC_CNF
[14:52:12.148,556] [GATEWAY/LSTN] PKTBODY:                                                          status = STATUS_FAILURE
[14:52:12.148,679] [GATEWAY/LSTN] PKTBODY:                                                          sequenceNumber = 0x000001A1 (417)

Proposed fix:
Increase the size of the heap in the CC2530/1 ZNP project. By default, it is 2170 bytes for the ZNP project which is too small for some applications.

You can increase the size of the heap by adding this compile flag to your project's Preprocessor Defined Symbols:

MAXMEMHEAP=2800

To further increase the heap (or for general RAM/Flash optimizations) check SWRA635

12. ZC sends ZEDs Leave Reqs after MAC Association

Issue description:
When trying to join a large number of ZEDs at once, ZC will sometimes send ZEDs Leave (w/ Rejoin) Requests. This is due to the network layer data buffers overflowing. If ZC is unable to buffer the Transport Key packet to the ZED due to lack of space in the network layer data buffers (for buffering indirect messages for sleepy children), ZC will discard the Transport Key and then remove the device from it's association table. Then, the next time that ZED polls the ZC for data, the ZC will send it a Leave Request because the ZC believes it is "rogue" since that ZED is not in it's association table.

Proposed fix:
1. Stagger the joining of ZED devices, i.e. make your join event sporadic (osal_rand() % 30000) <--- random amount of time between 0 and 30 seconds

2. Join less ZEDs at once

3. Increase the number of network layer data buffers, if RAM permits:

// in nwk_globals.c
// doubling the size of all the buffers:

// Maximums for the data buffer queue
#define NWK_MAX_DATABUFS_WAITING    16 //8     // Waiting to be sent to MAC
#define NWK_MAX_DATABUFS_SCHEDULED  10 //5     // Timed messages to be sent
#define NWK_MAX_DATABUFS_CONFIRMED  10 //5     // Held after MAC confirms
#define NWK_MAX_DATABUFS_TOTAL      24 //12    // Total number of buffers

13. APS ACK transID parameter error if using zcl_TransID

Issue description:
zcl_TransID is used as the parameter of AF_DataRequest() in zcl_SendCommand() but is always zero. It was only used since it doesn't affect the APS frame and since the APS header has the correct sequence number only the APS ACK validation is affected. Therefore zcl_TransID becomes obsolete after being removed from this function.

Proposed fix:
Use APS_Counter instead since this variable is incremented each time an APS frame is generated in APSDE_FrameHdrSet() and has the count of APS frames

// in External Variables section of zcl.c
extern uint8 APS_Counter;

// in zcl_SendCommand() of zcl.c
// Fill in the command frame
zcl_memcpy( pBuf, cmdFormat, cmdFormatLen );

status = AF_DataRequest( destAddr, epDesc, clusterID, msgLen, msgBuf,
                         &APS_Counter, options, AF_DEFAULT_RADIUS);
zcl_mem_free ( msgBuf );

14. BDB reporting doesn't support read/write attribute data callback functions

Issue description:
The current BDB reporting implementation doesn't support attributes that use a callback function to read/write attribute data.

Proposed fix:
Replace bdb_RepFindAttrEntry() in bdb_reporting.c

uint8 gAttrDataValue[BDBREPORTING_MAX_ANALOG_ATTR_SIZE];

static uint8 bdb_RepFindAttrEntry( uint8 endpoint, uint16 cluster, uint16 attrID, zclAttribute_t* attrRes )
{
  epList_t *epCur = epList;
  uint8 i;

  zcl_memset(gAttrDataValue, 0, BDBREPORTING_MAX_ANALOG_ATTR_SIZE);
  for ( epCur = epList; epCur != NULL; epCur = epCur->nextDesc )
  {
    if( epCur->epDesc->endPoint == endpoint )
    {
      zclAttrRecsList* attrItem = zclFindAttrRecsList( epCur->epDesc->endPoint );
      
      if( (attrItem != NULL) && ( (attrItem->numAttributes > 0) && (attrItem->attrs != NULL) ) )
      {
        for ( i = 0; i < attrItem->numAttributes; i++ )
        {
          if ( ( attrItem->attrs[i].clusterID == cluster ) && ( attrItem->attrs[i].attr.attrId ==  attrID ) )
          {
            uint16 dataLen;

            attrRes->attrId = attrItem->attrs[i].attr.attrId;
            attrRes->dataType = attrItem->attrs[i].attr.dataType;
            attrRes->accessControl = attrItem->attrs[i].attr.accessControl;

            dataLen = zclGetDataTypeLength(attrRes->dataType);
            zcl_ReadAttrData( endpoint, cluster, attrRes->attrId, gAttrDataValue, &dataLen );
            attrRes->dataPtr = gAttrDataValue;
            return BDBREPORTING_TRUE;
          }
        }
      }
    }
  }
  return BDBREPORTING_FALSE;
 }

15. Errors due to BDB header build types

Issue description:
Some identifiers are left undefined if -DZSTACK_DEVICE_BUILD="(DEVICE_BUILD_ROUTER | DEVICE_BUILD_ENDDEVICE)" (from znp.cfg).

Proposed fix:
Replace bdb.h include and macros sections:

#if (ZG_BUILD_JOINING_TYPE || (ZSTACK_DEVICE_BUILD == DEVICE_BUILD_ROUTER) || (ZSTACK_DEVICE_BUILD == DEVICE_BUILD_ENDDEVICE)) // ++ CHANGE THIS LINE
//Optional
  #if defined ( INTER_PAN ) && ( defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET ) )
    #define BDB_TOUCHLINK_CAPABILITY_ENABLED 1
  #else
    #define BDB_TOUCHLINK_CAPABILITY_ENABLED 0
  #endif
#else
  #if defined ( INTER_PAN ) && ( defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET ) )
    #error TouchLink cannot be enabled for coordinator. Please make sure not to define either BDB_TL_INITIATOR or BDB_TL_TARGET
  #endif
#endif

/*********************************************************************
 * MACROS
 */
  
// bdbNodeCommissioningCapability MACROS  
#if (ZG_BUILD_COORDINATOR_TYPE) 
  #define BDB_NETWORK_STEERING_CAPABILITY (BDB_NETWORK_STEERING_CAPABILITY_ENABLED<<0)
  #define BDB_NETWORK_FORMATION_CAPABILITY (BDB_NETWORK_FORMATION_CAPABILITY_ENABLED<<1)
  #define BDB_FINDING_BINDING_CAPABILITY (BDB_FINDING_BINDING_CAPABILITY_ENABLED<<2)
  #define BDB_TOUCHLINK_CAPABILITY (0<<3) //ZC cannot perform TL proceedure
#endif
#if (ZG_BUILD_JOINING_TYPE || (ZSTACK_DEVICE_BUILD == DEVICE_BUILD_ROUTER )) // ++ CHANGE THIS LINE
  #define BDB_NETWORK_STEERING_CAPABILITY (BDB_NETWORK_STEERING_CAPABILITY_ENABLED<<0)
  #define BDB_NETWORK_FORMATION_CAPABILITY (BDB_ROUTER_FORM_DISTRIBUTED_NWK_ENABLED<<1)
  #define BDB_FINDING_BINDING_CAPABILITY (BDB_FINDING_BINDING_CAPABILITY_ENABLED<<2)
  #define BDB_TOUCHLINK_CAPABILITY (BDB_TOUCHLINK_CAPABILITY_ENABLED<<3) 
#endif    
#if (ZG_BUILD_ENDDEVICE_TYPE)
  #define BDB_NETWORK_STEERING_CAPABILITY      (BDB_NETWORK_STEERING_CAPABILITY_ENABLED<<0)
  #define BDB_NETWORK_FORMATION_CAPABILITY     (0<<1)                                       //ZED cannot form nwk
  #define BDB_FINDING_BINDING_CAPABILITY       (BDB_FINDING_BINDING_CAPABILITY_ENABLED<<2)
  #define BDB_TOUCHLINK_CAPABILITY             (BDB_TOUCHLINK_CAPABILITY_ENABLED<<3)      
#endif  

Modify f8wCoord.cfg by commenting coordinator setting and adding router and device build:

/* Coordinator Settings */
//-DZDO_COORDINATOR // Coordinator Functions
//-DRTR_NWK

/* Generic All-in-One Settings */
-DZSTACK_DEVICE_BUILD="(DEVICE_BUILD_ROUTER | DEVICE_BUILD_ENDDEVICE)"

/* Other Settings */
-DNWK_AUTO_POLL

Change the device library with -C $PROJ_DIR$\..\..\..\Libraries\TI2530DB\bin\AllDevice-Pro.lib and replace all instances of #if ( ZSTACK_ROUTER_BUILD ) || defined ( ZBIT ) with #if ( ZSTACK_ROUTER_BUILD ) || (ZG_BUILD_ENDDEVICE_TYPE) || defined ( ZBIT )

16. Low Power Mode not Entered upon ZED Rejoin

Issue description:
The ZED device state is incorrectly set during rejoin, therefore bypassing the entry into standby and remaining active. This results in higher current consumption than should be expected.

Proposed fix:
Change DEV_END_DEVICE to DEV_NWK_SEC_REJOIN_CURR_CHANNEL inside the BDB_PARENT_LOST and BDB_INITIALIZATION cases of bdb_reportCommissioningState from bdb.c

17. Low Power Mode not Entered upon ZED Factory New Before Commissioning

Issue description:
High current consumption at ZED startup from factory new before being commissioned into a network.

Proposed fix:
Change the following inside osal_pwrmgr.c:

#include "ZGlobals.h"
void osal_pwrmgr_init( void )
{
#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS
#if defined POWER_SAVING && ZSTACK_END_DEVICE_BUILD                  
  pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY;   // Default to power conservation for ZED if power saving enabled.
#else
  pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON; // No power conservation for routing devices.
#endif
#endif /* USE_ICALL */
  pwrmgr_attribute.pwrmgr_task_state = 0;            // Cleared.  All set to conserve
#if defined USE_ICALL || defined OSAL_PORT2TIRTOS
  pwrmgr_initialized = TRUE;
#endif /* defined USE_ICALL || defined OSAL_PORT2TIRTOS */
}

18. ZED Poll Rate Set Incorrectly if Reset from a Leave Request with Rejoin Enabled

Issue description:
ZED will poll using REJOIN_POLL_RATE instead of POLL_RATE after being reset due to a parent leave request where the rejoin option was set.

Proposed fix:
In ZDApp_ProcessNetworkJoin of ZDApp.c, remove NLME_SetPollRate( zgRejoinPollRate ); from if (nwkStatus == ZSuccess) and place in the else statement instead. One must also set the zgRejoinPollRate when device state is DEV_END_DEVICE_UNAUTH

if ( ZG_SECURE_ENABLED && ( ZDApp_RestoreNwkKey( TRUE ) == false ) )
{
  if ( ZSTACK_END_DEVICE_BUILD )
  {
     NLME_SetPollRate( zgRejoinPollRate );
  }
  // wait for auth from trust center
  ZDApp_ChangeState( DEV_END_DEVICE_UNAUTH );

Optimally, also place NLME_SetPollRate( ZDApp_SavedPollRate ); inside of ZDO_JoinConfirmCB.

19. Memory Leak in the F&B Function of BDB

Issue description:
Memory leak in bdb_ProcessSimpleDesc()

Proposed fix:
Add bdb_zclSimpleDescClusterListClean( &bdb_FindingBindingTargetSimpleDesc ); before returning if the Simple Descriptor Response was not requested by BDB F&B

  //Just for safety check this is a valid entry
  if(pCurr != NULL) 
  {
    uint8 extAddr[Z_EXTADDR_LEN]; 
    
    if(AddrMgrExtAddrLookup( pCurr->data.addr.shortAddr, extAddr ))
    {
      isRespondantReadyToBeAdded = TRUE;
    }
    else
    {
      //Save the simple desc to don't ask for it again
      pCurr->SimpleDescriptor = &bdb_FindingBindingTargetSimpleDesc;
    }
    (void)extAddr;  //dummy
  }
  else
  {
    //This simple desc rsp was not requested by BDB F&B
    bdb_zclSimpleDescClusterListClean( &bdb_FindingBindingTargetSimpleDesc );  // +++ ADD THIS CODE
    return;
  } 

20. Large number of Address Manager Entries Results in Long ZC Startup Times

Issue description:
When increasing the number of NWK_MAX_ADDRESSES values stored in the ZCD_NV_ADDRMGR item (through increasing ZDSECMGR_TC_DEVICE_MAX and NWK_MAX_DEVICE_LIST), the large number of osal_nv_write calls required to initialize the NV items during NLME_InitNV() will cause a long delay in startup time.

Proposed fix:
Initialize large portions of the Address Manager NV item instead of one byte at a time, an example of which can be accomplished by modifying ZDApp.c as such:

#define ADDR_MGR_ENTRY_SIZE     12
uint8 Custom_AddrMgr_InitNV(void);
//...
uint8 ZDOInitDeviceEx( uint16 startDelay, uint8 mode)
{
//...
  else
  {
    // Wipe out the network state in NV
    Custom_AddrMgr_InitNV();  //ADD THIS LINE
    NLME_InitNV();
    NLME_SetDefaultNV();
    // clear NWK key values
    ZDSecMgrClearNVKeyValues();
  }
//...
uint8 ZDApp_RestoreNetworkState( void )
{
  uint8 nvStat;

  nvStat = Custom_AddrMgr_InitNV();
  nvStat |= NLME_InitNV();
//...
uint8 Custom_AddrMgr_InitNV( void )
{
  uint8 ret = SUCCESS;
  uint8  status, ctrl[NWK_MAX_ADDRESSES*ADDR_MGR_ENTRY_SIZE];
  uint16 size, index, offset;

  // Initialize the NIB NV item
  if ( osal_nv_item_init( ZCD_NV_NIB, sizeof(nwkIB_t), &_NIB ) == NV_OPER_FAILED )
    ret |= NV_NIB_INIT_FAILURE;

  size = (uint16)( ADDR_MGR_ENTRY_SIZE * NWK_MAX_ADDRESSES );

  status = osal_nv_item_init( ZCD_NV_ADDRMGR, size, NULL );

  if (status == NV_ITEM_UNINIT) 
  {
    for ( index = 0; index < NWK_MAX_ADDRESSES; index++ )
    {
      ctrl[index] = 0x00;
    }
    for ( index = 0; index < ADDR_MGR_ENTRY_SIZE; index++ )
    {
      offset = NWK_MAX_ADDRESSES * index;
      osal_nv_write( ZCD_NV_ADDRMGR, offset, NWK_MAX_ADDRESSES, &ctrl );
    }
  };

  if ( status == NV_OPER_FAILED ) ret |= NV_ADDR_MGR_INIT_FAILURE;
  
  return ( ret );
}

HAL_NV_PAGE_CNT and OSAL_NV_PHY_PER_PG will also need to increase accordingly. OSAL_NV_PHY_PER_PG*2048 must be greater than NWK_MAX_ADDRESSES*12 (the size of AddrMgrEntryData_t) and the CC2538.icf FLASH and NV_MEM regions should compensate for changes to HAL_NV_PAGE_CNT

21. Inclusion of HAL_PA_LNA_CC2592 did not Propagate to ZNP Project

Issue description:
Consideration for cases involving HAL_PA_LNA_CC2592 inside of hal_board_cfg.h were not applied to the ZNP project as compared to all Home Automation examples. Therefore, if building the ZNP project with HAL_PA_LNA_CC2592 defined and the CC2592 connected to the CC253x device there will be radio communication issues.

Proposed fix:
Add HAL_PA_LNA_CC2592 to hal_board_cfg.h as so:

// #ifdef HAL_PA_LNA //----------------Remove the line ---------
#if defined HAL_PA_LNA || defined HAL_PA_LNA_CC2592 // ++++++ ADD This line ++++++++
#define HAL_BOARD_PA_LNA_INIT() st(GPIOPinTypeGPIOOutput(HGM_BASE, HGM_PIN); )
#else
#define HAL_BOARD_PA_LNA_INIT()
#endif

/* ----------- RF-frontend Connection Initialization ---------- */
//#if defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590 //----------Remove the line -----
#if defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590 || defined HAL_PA_LNA_CC2592
//++++++++ADD the above Line ++++++++++
extern void MAC_RfFrontendSetup(void);
#define HAL_BOARD_RF_FRONTEND_SETUP() MAC_RfFrontendSetup()
#else
#define HAL_BOARD_RF_FRONTEND_SETUP()
#endif
  // Initialize the NIB NV item
  if ( osal_nv_item_init( ZCD_NV_NIB, sizeof(nwkIB_t), &_NIB ) == NV_OPER_FAILED )
    ret |= NV_NIB_INIT_FAILURE;

  size = (uint16)( ADDR_MGR_ENTRY_SIZE * NWK_MAX_ADDRESSES );

  status = osal_nv_item_init( ZCD_NV_ADDRMGR, size, NULL );

  if (status == NV_ITEM_UNINIT) 
  {
    for ( index = 0; index < NWK_MAX_ADDRESSES; index++ )
    {
      ctrl[index] = 0x00;
    }
    for ( index = 0; index < ADDR_MGR_ENTRY_SIZE; index++ )
    {
      offset = NWK_MAX_ADDRESSES * index;
      osal_nv_write( ZCD_NV_ADDRMGR, offset, NWK_MAX_ADDRESSES, &ctrl );
    }
  };

  if ( status == NV_OPER_FAILED ) ret |= NV_ADDR_MGR_INIT_FAILURE;
  
  return ( ret );
}

This fix only applies to the ZNP project as the Home Automation examples already have this fix

22. Multiple attribute reporting issue

Issue description:
When reporting multiple attributes from a cluster, all attributes have the same value.

Proposed fix:
Replace your bdb_RepReport() function in bdb_Reporting.c as such:

static void bdb_RepReport( uint8 specificCLusterEndpointIndex )
{
  afAddrType_t dstAddr;
  zclReportCmd_t *pReportCmd = NULL;
  uint8 i;
  
  bdbReportAttrClusterEndpoint_t* clusterEndpointItem = NULL;
  if( specificCLusterEndpointIndex == BDBREPORTING_INVALIDINDEX )
  {
    if( bdb_reportingNextClusterEndpointIndex < bdb_reportingClusterEndpointArrayCount )
    {
      clusterEndpointItem = &(bdb_reportingClusterEndpointArray[bdb_reportingNextClusterEndpointIndex]);
    }
  }
  else
  {
    clusterEndpointItem = &(bdb_reportingClusterEndpointArray[specificCLusterEndpointIndex]);
  }

  // actually send the report
  if( clusterEndpointItem->consolidatedMaxReportInt != ZCL_REPORTING_OFF && clusterEndpointItem->attrLinkedList.numItems )
  {
    uint8 *pAttrData = NULL;
    uint8 *pAttrDataTemp = NULL;
    
    dstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
    dstAddr.addr.shortAddr = 0;
    dstAddr.endPoint = clusterEndpointItem->endpoint;
    dstAddr.panId = _NIB.nwkPanId;
    
    // List of attributes to report
    pReportCmd = osal_mem_alloc( sizeof( zclReportCmd_t ) + (clusterEndpointItem->attrLinkedList.numItems * sizeof( zclReport_t )) );
    // List of attribute data
    pAttrData = osal_mem_alloc(clusterEndpointItem->attrLinkedList.numItems * BDBREPORTING_MAX_ANALOG_ATTR_SIZE);
    if ( (pReportCmd != NULL) && (pAttrData != NULL) )
    {
      pAttrDataTemp = pAttrData;
      pReportCmd->numAttr = clusterEndpointItem->attrLinkedList.numItems;
      for ( i = 0; i < clusterEndpointItem->attrLinkedList.numItems; ++ i )
      {
        pReportCmd->attrList[i].attrID   = 0xFFFF;
        pReportCmd->attrList[i].dataType = 0xFF;
        pReportCmd->attrList[i].attrData = NULL;
        
        bdbLinkedListAttrItem_t* attrListItem = bdb_linkedListAttrGetAtIndex( &clusterEndpointItem->attrLinkedList, i );      
        if(attrListItem!=NULL)
        {
          zclAttribute_t attrRec;
          pReportCmd->attrList[i].attrID = attrListItem->data->attrID;   
          uint8 attrRes = bdb_RepFindAttrEntry( clusterEndpointItem->endpoint, clusterEndpointItem->cluster, attrListItem->data->attrID, &attrRec );
          if( attrRes == BDBREPORTING_TRUE )
          {
            pReportCmd->attrList[i].dataType = attrRec.dataType;
            pReportCmd->attrList[i].attrData = pAttrDataTemp;
            // Copy data to current attribute data pointer
            pAttrDataTemp = osal_memcpy(pAttrDataTemp, attrRec.dataPtr, BDBREPORTING_MAX_ANALOG_ATTR_SIZE);
                      
            //Update last value reported
            if( zclAnalogDataType( attrRec.dataType ) )
            { 
              //Only if the datatype is analog
              osal_memset( attrListItem->data->lastValueReported,0x00, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );
              osal_memcpy( attrListItem->data->lastValueReported, attrRec.dataPtr, zclGetDataTypeLength( attrRec.dataType ) );
            }
          }
        }
      }

      zcl_SendReportCmd( clusterEndpointItem->endpoint, &dstAddr,
                         clusterEndpointItem->cluster, pReportCmd,
                         ZCL_FRAME_SERVER_CLIENT_DIR, BDB_REPORTING_DISABLE_DEFAULT_RSP, bdb_getZCLFrameCounter( ) );
    }
    if( (pReportCmd != NULL ) )
    {
      osal_mem_free( pReportCmd );
    }
    if ( (pAttrData != NULL) )
    {
      osal_mem_free( pAttrData );
    }
  }
}

23. ZNP initializes GP proxy table with the wrong item ID

Issue description:
ZDOInitDeviceEx of ZDApp.c doubles the NV item ID start location of ZCD_NV_PROXY_TABLE_START when DISABLE_GREENPOWER_BASIC_PROXY & ZG_BUILD_RTR_TYPE are defined (applies to the ZNP project):

Proposed fix:
Modify ZDApp.c as follows:

    for( i = ZCD_NV_PROXY_TABLE_START; i <= ZCD_NV_PROXY_TABLE_END; i++ )
    {
      status = osal_nv_write( ( i ), 0,   //MODIFIED TO REMOVE ZCD_NV_PROXY_TABLE_START
                                          sizeof(emptyEntry), &emptyEntry );
      
      if( status != SUCCESS )
      {
        break;
      }
    }

24. Frame counter does not increment on device reset

Issue description:
On a device reset, the frame counter is supposed to increment by MAX_NWK_FRAMECOUNTER_CHANGES + NWK_FRAMECOUNTER_CHANGES_RESTORE_DELTA to account for frames transmitted between the last NV update and a device reset.  However, ZDApp_RestoreNwkSecMaterial attempts to write the incorrect ZCD_NV_EX_NWK_SEC_MATERIAL_TABLE and thus fails to update the frame counter appropriately.  This could lead to Zigbee packets being ignored after the device restart to due frame counter inconsistency.

Proposed fix:
Modify ZDApp_RestoreNwkSecMaterial from ZDApp.c as follows:

  //Check if we do have frame counter stored in the generic
  if(!Found)
  {
    // If we did not find the current network in NV, overwrite the generic entry,
    // which is the last entry in the table.
    if(nwkSecMaterialDesc.FrameCounter)
    {
      UpdateFrameCounter = TRUE;
      i = (gMAX_NWK_SEC_MATERIAL_TABLE_ENTRIES - 1);  // ADD THIS LINE
    }
  }