Z-Stack 3.0.1 已知问题和建议的解决方案



点击左上角的“关注”,定期更新 Zigbee 最新资讯,总有你想要的信息!

Z-Stack 3.0.1 已知问题和建议的解决方案


摘要

  本文档包含 TI 发布的 Zigbee 软件版本中的已知问题。 TI 有一个测试的软件版本,所有的修复程序在更新后可能不会立即提供给开发人员。 此文档的目的是向开发人员提供已知问题和修复方法,以防在发布新版本之前在已发布的软件上发生问题。 这将帮助开发人员在 TI 发布已修复问题的 Zigbee 版本之前解决问题。


1. Z-Stack 3.0.1 问题与修复

1.1 zcl.c 内存泄漏

  • 问题描述
      zcl_HandleExternal() 函数存在内存泄漏问题。
  • 建议修复方法
zcl_HandleExternal()
{
...
#ifdef BDB_REPORTING
	if(pCmd->zclHdr.commandID == ZCL_CMD_CONFIG_REPORT)
	{
		bdb_ProcessInConfigReportCmd(pCmd);
		osal_msg_deallocate((uint8 *)pCmd); // ++++++++++++++ 添加此处代码
		return TRUE;
	}
	if(pCmd->zclHdr.commandID == ZCL_CMD_READ_REPORT_CFG)
	{
		bdb_ProcessInReadReportCfgCmd(pCmd);
		osal_msg_deallocate((uint8 *)pCmd); // ++++++++++++++ 添加此处代码
	return TRUE;
	}
#endif
...
}

1.2 APS Remove or Leave Request 后,网络关联问题

  • 问题描述
      在某些情况下,当 APS “Remove/Leave Request” 被发送到某个设备以移除自身或另一个设备时,由于 TC 链路密钥交换中的旧 APS 密钥仍然存在 NV 中, 所以无法清除 NV,导致设备无法建立新的网络连接。
  • 建议修复方法
// 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 ); /// ++++ 修改此代码 ++++
			// The device has been in the UNAUTH state, so reset// Note: there will be no return from this call
			SystemResetSoft();
		}
	}
...
}

1.3 CC2530/CC2531 上的 “BDB_REPORTING” 导致软件复位/冻结/堆栈溢出

  • 问题描述
      “XDATA” 堆栈的默认大小为 0x300(768 个字节),但是在应用程序中添加 “BDB_REPORTING” 功能时, 会导致有时调用堆栈太大而溢出 “XDATA” 堆栈。
  • 建议修复方法
      将项目选项中 “XDATA” 堆栈的大小至少增加到 0x400:
    在这里插入图片描述

1.4 从 ZHA 1.2 通过 OTA 升级到 Z3.0 导致设备损坏

  • 问题描述
      从 ZHA 1.2 通过 OTA 升级到 Zigbee 3.0 时,某些 NV 项的使用在不同版本之间发生了变化,网络安全信息的格式也不同。因此,我们有必要在升级时“升级”一些 NV 安全项目。
  • 建议修复方法
      下面的一些代码已经存在于 Z-Stack 中,并作为上下文提供。添加此修复程序的所有代码更改都在编译标志 “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

1.5 CC2538 ZNP 的 IEEE 地址报告错误

  • 问题描述
      在使用 CC2538 ZNP 项目时,IEEE 地址的 MSB 和 LSB 被翻转。这是由于 IEEE 地址在 CC2538 SoC 设备的测试版本和生产版本之间的变化。非 ZNP CC2538 项目不受影响,因为它们使用了不同的 ZMain.c 文件,该文件已经应用了此修复程序。
  • 建议修复方法
// 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);
}

...

1.6 修改 CC2538 Linker 来使用所有的 32k RAM 时会导致锁定

  • 问题描述
      某些 CC2538 芯片有 32k 的 RAM,但是在默认情况下,Linker 文件会禁用前 16k 的 RAM,因为只有后 16k 的 RAM 可以在所有功耗模式下使用。当设备进入 PM2 时,前 16k 的 RAM 会丢失其内容。如果我们要设计的设备永远不会进入低功耗模式,则可以开启前 16k 的 RAM 以供应用程序使用。我们可以通过更改 Linker 文件中的以下内容来执行此操作:
//
// Define a region for the on-chip SRAM.
//
define region SRAM = mem:[from 0x20000000 to 0x20007FFF]; // 0x20004000 --> 0x20000000

  但是,在某些应用程序中,将 RAM 增加到这个值会导致 Z-Stack 锁定。

  • 建议修复方法
      将 run-time 堆栈移到 RAM 的末尾。 在 Linker 文件中找到以下代码,并进行以下更改:
//
// 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 }; // ++++++++++ 添加此代码 ++++++++++

1.7 ZED 不接收从父节点发送到 MAC dst 0xFFFF 的广播

  • 问题描述
      在 Zigbee 中,如果广播一条目的地址为 0xFFFF 的消息,所有设备 (Rx 始终打开和处于休眠状态) 都将接收该消息。这意味着父节点路由设备必须为其处于休眠状态的 ZED 子设备缓冲此目的地址为 0xFFFF 的广播消息。在 Z-Stack 中,如果有单个 ZR/ZC 节点有超过 (32 个 MAX_NEIGHBOR_ENTRIES) 个休眠的 ZED 子节点,则超出此数目的所有 ZED 将无法接收广播消息。对于 Z-Stack 中的路由设备,默认情况下,“MAX_NEIGHBOR_ENTRIES” 为 16。

  • 建议修复方法
      由于此过程实现是在预编译的 Z-Stack 库中,因此目前没有完美的解决方法,但是我们可以建议一些解决方法:
    (1)不要发送目的地址为 0xFFFF 的广播消息,只使用目的地址为 0xFFFC/0xFFFD (仅发送给 Rx 始终打开的设备) 的广播消息,对休眠的 ZED 节点只发送单播消息。

    • 这是首选方法,因为我们不必因此限制设备表的大小。

    (2) 将每个 ZC/ZR 的休眠 ZED 节点数限制为最多 16 个。

    • 无论如何,对于大型网络来说,这都是一个好习惯,对于健壮的网状网络拓扑,我们应该始终以每 10-15 个 ZED 设置一个ZR。

    (3) 将 “MAX_NEIGHBOR_ENTRIES” 从 16 减少到较小的值。

    • 不建议使用 “MAX_NEIGHBOR_ENTRIES” 来确定邻居表的大小,邻居表是设备RF范围内的ZR设备的列表。更大的邻居表=更容易的 Zigbee 路由发现=更健壮的网状网络。TI Z-Stack 已使用 “MAX_NEIGHBOR_ENTRIES=16” 进行了测试,对于大多数 Zigbee 网络环境而言,它都是一个很好的数值。

1.8 当 ZED 在调试期间进行轮询(传输密钥,请求简单描述符等)时,NWK / APS 数据包重发/失败问题

  • 问题描述
      有时 ZC 在网络调试期间无法发送 NWK/APS 层数据包,例如将传输密钥传输到加入的 ZED,这要求 ZED 再次轮询以获取数据包。虽然这不会对加入设备造成功能问题,因为它会重试并最终获得数据包,但需要多次重试以接收同一数据包的情况并不理想。此问题是因为新的设备加入网络后,ZC 会发生阻塞 NV 写入操作。
  • 建议修复方法
      将 “ZDAPP_UPDATE_NWK_NV_TIME” 的值从默认值 700(ms) 更改为更大的值,如 3500。这会使 NV 写入操作延后启动,因此不会干扰网络调试。

1.9 在失去父节点并尝试恢复网络后,ZED 不会返回低功耗状态

  • 问题描述
      应用程序调用 API “bdb_ZedAttemptRecoverNwk()” 尝试让 ZED 重新加入网络后,接收器并未关闭,这导致 ZED 在空闲期间将 RX 保持打开状态,并且不会进入低功耗状态。
  • 建议修复方法
      在 bdb.c 中修改函数 bdb_parentLost():
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;                      // ++++++++++++++ 添加此代码
    ZMacSetReq(ZMacRxOnIdle, &temp);     // ++++++++++++++ 添加此代码

    bdb_reportCommissioningState(BDB_PARENT_LOST,FALSE);
  }
#endif
}

1.10 Chatting 和 Voice 的 ZCL ID 错误

  • 问题描述
      Chatting 和 Voice 的 ZCL ID 错误
  • 建议修复方法
// 当前的Chatting和Voice的ZCL ID
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_CHATTING             0x0904
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE  0x0905

// ID应像这样调换:
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_CHATTING             0x0905
#define ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE  0x0904

1.11 CC2530/1 ZNP 设备偶尔返回 zMerror

  • 问题描述
      有时在我们的 Zigbee Linux 网关解决方案中,CC2530/1znp 设备会返回一条状态为 zmerError 的失败消息,如下所示。
[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)

  • 建议修复方法
      在 CC2530/1 znp 项目中增加堆的大小。默认情况下,ZNP 项目的字节数为 2170,这对于某些应用程序来说太小了。通过将此编译标志添加到项目的预处理器定义的符号中,可以增加堆的大小:MAXMEMHEAP=2800。要进一步增加堆 (或常规 RAM/Flash 优化),请查看以下 wiki 页面:http://processors.wiki.ti.com/index.php/Optimizing_Flash_and_RAM_Usage_of_Z-Stack_for_CC2530

1.12 MAC 关联后,ZC 发送 Leave Reqs 给 ZED

  • 问题描述
      当尝试一次性加入大量 ZED 时,ZC 有时会发送 ZED Leave (带有重新加入)请求。这是由于网络层数据缓冲区溢出造成的。如果 ZC 因为网络层数据缓冲区(为休眠子节点缓存数据)中的空间不足而无法将传输密钥包缓冲到 ZED,则 ZC 将丢弃传输密钥,然后从关联表中删除该设备。然后,当下次 ZED 向 ZC 轮询数据时,因为 ZED 不在 ZC 的关联表中,因此 ZC 认为它是“流氓”,所以 ZC 将向其发送 Leave Request。
  • 建议修复方法
    (1) 使 ZED 设备错开入网,例如:将 ZED 入网变为随机事件,随机时间在(osal_rand() % 30000),0 到 30 秒之间错峰加入。
    (2) 一次性只让少量的 ZED 设备同时请求入网。
    (3) 如果 RAM 允许,增加网络层数据缓冲区的数量:
// 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

1.13 如果使用 zcl_TransID,则 APS ACK transID 参数错误

  • 问题描述
      zcl_TransID 用作 zcl_SendCommand() 中 AF_DataRequest() 的参数,但始终为零。之所以使用它是因为它不影响 APS 帧,并且因为 APS 帧头具有正确的序列号,所以仅影响 APS ACK 帧的验证。
  • 建议修复方法
      请使用 APS_Counter 代替 zcl_TransID,因为每次在 APSDE_FrameHdrSet() 中生成 APS 帧且具有 APS 帧计数时,此变量都会递增。
// 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 );

1.14 BDB Reporting 不支持读/写属性数据回调函数

  • 问题描述
      当前的 BDB Reporting 实现不支持使用回调函数读/写属性数据的属性。
  • 建议修复方法
      替换 bdb_reporting.c 中的 bdb_RepFindAttrEntry()。
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;
 }

1.15 由于 BDB 头生成类型而导致的错误

  • 问题描述
      如果是 -DZSTACK_DEVICE_BUILD ="(DEVICE_BUILD_ROUTER | DEVICE_BUILD_ENDDEVICE)"(来自 znp.cfg),则某些标识符将保持未定义状态。
  • 建议修复方法
      替换 “bdb.h” 中的 include 和 macros 部分:
#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  

  通过注释协调器设置并添加路由器和设备构建来修改 f8wCoord.cfg:

/* 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

  更改设备库“-C $PROJ_DIR$\..\..\..\Libraries\TI2530DB\bin\AllDevice-Pro.lib”,并且将所有实例中的“#if ( ZSTACK_ROUTER_BUILD ) || defined ( ZBIT )”改成“#if ( ZSTACK_ROUTER_BUILD ) || (ZG_BUILD_ENDDEVICE_TYPE) || defined ( ZBIT )”

1.16 ZED 重新连接时未进入低功率模式

  • 问题描述
      重新连接期间,ZED 设备状态设置不正确,因此绕过进入待机状态并保持活动状态。这会导致电流消耗超出预期。
  • 建议修复方法
      从 bdb.c 将 bdb_reportCommissioningState 的 BDB_PARENT_LOST 和 BDB_INITIALIZATION 案例内的 DEV_END_DEVICE 更改为 DEV_NWK_SEC_REJOIN_CURR_CHANNEL。

1.17 调试前 ZED 出厂设备未进入低功率模式

  • 问题描述
      ZED 启动时会先进入高功耗的出厂设备状态,然后才被调试成网络。
  • 建议修复方法
      在 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 */
}

1.18 收到 Leave Request (使能重新加入)命令重置后,ZED 轮询速度错误问题

  • 问题描述
      因为收到的 “leave request” 命令设置了 “rejoin” 选项,ZED 在重置后将使用 “REJOIN_POLL_RATE” 而不是 “POLL_RATE” 进行轮询。
  • 建议修复方法
      在 ZDApp.c 的 ZDApp_ProcessNetworkJoin() 函数中,从 if(nwkStatus==ZSuccess) 中删除 “NLME_SetPollRate(zgRejoinPollRate);”,并将其放在 else 语句中。当设备状态为 “DEV_END_DEVICE_UNAUTH” 时,还必须设置 zgRejoinPollRate。
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 );

  最好也将 “NLME_SetPollRate(ZDApp_SavedPollRate);” 放在 ZDO_JoinConfirmCB 的内部。

1.19 BDB 的 F&B 函数内存泄漏

  • 问题描述
      bdb_ProcessSimpleDesc() 函数存在内存泄漏。
  • 建议修复方法
      如果 BDB F&B 没有请求简单描述符响应,则在返回之前添加 “bdb_zclSimpleDescClusterListClean( &bdb_FindingBindingTargetSimpleDesc );”。
  //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;
  } 

1.20 大量的地址管理器条目导致ZC启动时间过长

  • 问题描述
      当增加 “ZCD_NV_ADDRMGR” 项目中存储的 “NWK_MAX_ADDRESSES” 值的数量(通过增加 ZDSECMGR_TC_DEVICE_MAX 和 NWK_MAX_DEVICE_LIST)时,在 NLME_InitNV() 期间初始化 NV 项目所需的大量 osal_nv_write() 调用将导致启动时间较长。
  • 建议修复方法
      初始化地址管理器 NV 项目的大部分而不是一次初始化一个字节,可以通过如下修改 ZDApp.c 来完成一个示例:
#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 和 OSAL_NV_PHY_PER_PG 也需要相应增加。OSAL_NV_PHY_PER_PG * 2048 必须大于 NWK_MAX_ADDRESSES * 12 (AddrMgrEntryData_t 的大小),并且 CC2538.icf FLASH 和 NV_MEM 区域应补偿对 HAL_NV_PAGE_CNT 的更改。

1.21 在 ZNP 项目中添加 HAL_PA_LNA_CC2592 却无作用

  • 问题描述
      与所有 Home Automation 实例相比,ZNP 项目不能直接打开 HAL_PA_LNA_CC2592 使用。因此,如果使用定义的 HAL_PA_LNA_CC2592 来构建 ZNP 项目并将 CC2592 连接到 CC253x 设备,会存在无线电通信问题。
  • 建议修复方法
      将 HAL_PA_LNA_CC2592 添加到 HAL_board_cfg.h 中,如下所示:
// #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 );
}


大家的支持就是我分享技术的动力,希望大家需转载时能附上原作者的博客:https://blog.csdn.net/u012993936,谢谢。



--- End ---
你可能还想看:

> 如何7天快速入门Zigbee?
> 免费的Zigbee抓包神器!比Ubiqua还好用!


文章都看完了,随手点个赞吧~
在这里插入图片描述
↓↓↓ ↓↓↓

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jesse_嘉伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值