CC2340R5: zigbee使用zcl多次发送固定数组数据后显示内存不足

Part Number: CC2340R5


如下方代码所示,先获取缓冲区,再使用zb_aps_send_user_payload()函数发送数据,发送完成或者失败后释放获得的缓冲区;
但是我使用定时每秒发送一次数据时,大约20分钟后程序就会卡死,显示内存错误,必须重新上电才能继续运行,且程序正常运行时间不确定。请问这是什么问题,这个代码是使用TI提供的例程中nortos->zigbee下面的onoff_light程序修改来的。望各位能够提供一点帮助,非常感谢。
 
 
zb_bufid_t param= zb_buf_get_out();
获取成功再执行下方函数,
zb_ret_t ret = zb_aps_send_user_payload(
//       param,
//       addr,                   /* dst_addr (协调器地址) */
//       0x0104,                 /* profile id (自定义应用配置文件) */
//       0xf00d,                 /* cluster id (自定义集群ID) */
//       ZB_OUTPUT_ENDPOINT,     /* destination endpoint (协调器的端点5) */
//       ZB_SWITCH_ENDPOINT,     /* source endpoint (终端设备的端点10) */
//       ZB_APS_ADDR_MODE_16_ENDP_PRESENT, /* address mode */
//       ZB_TRUE,                /* APS ACK enabled */
//       data_array,             /* payload pointer */
//       data_size);             /* size of payload */
   
//     if (ret != RET_OK) {
//         uartPrintf("Failed to send custom array, error code: %d\r\n", ret);
//         zb_buf_free(param);  /* 发送失败时释放缓冲区 */
//     } else {
//         // 发送成功,立即释放缓冲区
//         zb_buf_free(param);
//         uartPrintf("Custom array buffer freed after successful transmission\r\n");
//     }
//   }
  • 已经收到了您的案例,调查需要些时间,感谢您的耐心等待。

  • 在CCS中,能否使用内存分配和堆栈使用功能来检查是否有某种内存占用了过多空间?

  • 您这边可以进行代码运行吗?我这边初次接触ccs,对与里面的代码不熟悉,找不到对应函数,可以给您提供我这边的协调器以及终端代码

  • 没有找到相关检测函数
    和您描述一下我这边的现象吧:当不使用zb_aps_send_user_payload函数,只进行串口打印及其他功能时,程序不会卡死。
    但是一旦使用了zigbee数据发送函数,程序在运行一段时间后就会卡死,我设置的是每秒发送一条zigbee数据,自定义大小为34个字节。开始发送时协调器可以接收到数据,发送一段时间后,终端;可能会出现两种问题,一个是无法获取zigbee发送缓冲区,一个是打印内存不足错误;重新上电后,程序又可以运行一段时间。

    我不知道是不是因为zigbee数据发送太快导致的,但1s已经是我接受的底线了;想向您了解zb_aps_send_user_payload函数在数据发送后会不会自动释放空间,并且若是使用

    ZB_FALSE - 禁用APS确认,

    数据发送的速度是不是会大于1s,我不知道问题在哪。



    还有一个问题是我这边 IIC、ADC、UART都是在上电后就一直打开使用open函数,这会不会一直占用空间?
  • 能否提供给我一个CC2340R5芯片的zigbee数据收发例程,我这边其他外设都已经进行设置,应该没有什么问题,就是关于zigbee数据发送函数运用出现问题,使用一段时间程序就会卡死。

  • 目前我对自己的代码实在没有信心,贵公司关于CC2340R5芯片zigbee开发的例程以及相关技术资料实在太少了,我完全不知道该怎么使用才能完成正常的zigbee自定义数量数据收发功能。

  • 该参数类型为zb_uint8_t,仅在成功传输后才应从回调中释放。以下是其他资源:

     CC2340R5: The error "ZB_ZDO_DEVICE_UNAVAILABLE" occurred during the communication process. 
    ZBOSS User's Guide 
    Zigbee Fundamentals SLA 

  • 我这边的问题和您给的例子不一样,我的是终端可以一直发送数据,并不会显示无法连接;

    而是发送一段时间数据后终端uart打印显示


    这是在触发错误后打印的
    函数如下

    static zb_bool_t error_ind_handler(zb_uint8_t severity,
                                        zb_ret_t error_code,
                                        void *additional_info)
    {
      zb_bool_t ret = ZB_FALSE;
      ZVUNUSED(additional_info);
      /* Unused without trace. */
      ZVUNUSED(severity);

      // 使用串口打印详细的错误信息
      uartPrintf("=== ERROR HANDLER CALLED ===\r\n");
      uartPrintf("Error Severity: %d, Error Code: %d (0x%04X)\r\n", severity, error_code, error_code);
     
      // 解析错误类别
      zb_uint16_t error_category = (error_code >> 8) & 0xFF;
      zb_uint16_t error_subcode = error_code & 0xFF;
      uartPrintf("Error Category: 0x%02X, Subcode: 0x%02X\r\n", error_category, error_subcode);

      if (error_code == ERROR_CODE(ERROR_CATEGORY_MACSPLIT, ZB_ERROR_MACSPLIT_RADIO_HANG))
      {
        uartPrintf("!!! FATAL ERROR: MACSPLIT RADIO HANG !!!\r\n");
        uartPrintf("Cause: Radio module has stopped responding\r\n");
        uartPrintf("Action: Device will likely restart\r\n");

        ret = ZB_TRUE;
        /* return TRUE to prevent default error handling by the stack */
      }
      else if (error_code == ERROR_CODE(ERROR_CATEGORY_MACSPLIT, ZB_ERROR_MACSPLIT_RADIO_REBOOT))
      {
        uartPrintf("!!! RADIO REBOOT DETECTED !!!\r\n");
        uartPrintf("Cause: Radio module has been reset\r\n");
        uartPrintf("Action: Protocol stack recovery in progress\r\n");

        ret = ZB_TRUE;
      }
      else
      {
        // 其他错误类型的处理 - 允许默认处理
        uartPrintf("Unknown error type, allowing default handling\r\n");
        ret = ZB_FALSE;  // 确保返回FALSE,允许协议栈处理信号
      }
     
      uartPrintf("Error handler return value: %s\r\n", ret ? "TRUE (block default)" : "FALSE (allow default)");
      uartPrintf("=================================\r\n");
     
      return ret;
    }




    默认处理后终端重启,再次进行协调器连接并且发送数据,但是一段时间后会再次打印该错误并且重启
  • 我的问题和您给的案例不一样,我遇到的问题是终端在连接协调器后,在发送数据过程中大约10分钟左右,终端设备会发生重启现象,我查看了错误打印内容,发现问题提示为内存错误。

    而且该问题只有在设备使用zb_aps_send_user_payload函数时才会发生,若单纯的进行zigbee连接,并且申请、释放空间,程序是没有问题的,目前猜测导致内存不足的原因是zb_aps_send_user_payload函数使用后未及时释放空间,不知有没有其他问题?恳请解答。

  • 给您提供一下我的代码,当我使用数据发送函数zb_aps_send_user_payload时,不论发送是否成功都必须使用zb_buf_free(param);来释放空间,若是发送成功后不使用zb_buf_free(param);函数,则数据发送7次之后程序重启。。若数据发送成功后使用zb_buf_free(param);函数,则程序可以运行时间不定,约20分钟左右,会发生重启。


    /* 改进的ZCL标准格式数据发送函数
     * 参数: param - Zigbee缓冲区ID
     * 功能: 通过ZCL标准协议发送数据到父节点(协调器),包含错误处理和重试机制 */
    void send_zcl_payload(zb_uint8_t param)
    {
      zb_addr_u addr = { 0 };           /* Zigbee地址结构体 */
      zb_uint16_t parent = zb_nwk_get_parent();  /* 获取父节点(协调器)地址 */
     
      ZB_ASSERT(param);  /* 断言检查参数有效性 */
      uartPrintf("param2: %d\r\n", param);
      // Set target address to parent node (coordinator)
      if (parent != ZB_UNKNOWN_SHORT_ADDR) {
        addr.addr_short = parent;  /* Set target address to parent node short address */
      } else {
        uartPrintf("No parent node, cannot send data\r\n");
        zb_buf_free(param);  /* Release buffer */
        return;
      }

      {
        Log_printf(LogModule_Zigbee_App, Log_INFO, "send_zcl_data to parent: 0x%04x", parent);

        // Simplified log output to avoid overload
        uartPrintf("Sending ZCL frame to parent 0x%04X, size: %d bytes\r\n", parent, ZCL_FRAME_SIZE);

        /* Zigbee APS发送ZCL数据包
         * 参数说明:
         * param - 缓冲区ID
         * addr - 目标地址(父节点)
         * ZB_AF_HA_PROFILE_ID - 使用标准Home Automation配置文件ID (0x0104)
         * ZB_ZCL_CLUSTER_ID_BASIC - 使用标准基础集群ID (0x0000)
         * ZB_OUTPUT_ENDPOINT - 目标端点(协调器端点5)
         * ZB_SWITCH_ENDPOINT - 源端点(自定义端点10)
         * ZB_APS_ADDR_MODE_16_ENDP_PRESENT - 16位地址模式
         * ZB_FALSE - 禁用APS确认,避免ACK等待导致协调器积压
         * zclFrameData - ZCL帧数据指针
         * ZCL_FRAME_SIZE - ZCL帧大小 */
        zb_ret_t ret = zb_aps_send_user_payload(
          param,
          addr,                           /* dst_addr */
          ZB_AF_HA_PROFILE_ID,            /* profile id - 标准HA配置文件 */
          ZB_ZCL_CLUSTER_ID_BASIC,        /* cluster id - 基础集群 */
          ZB_OUTPUT_ENDPOINT,             /* destination endpoint (coordinator endpoint 5) */
          ZB_SWITCH_ENDPOINT,             /* source endpoint */
          ZB_APS_ADDR_MODE_16_ENDP_PRESENT, /* address mode */
          ZB_FALSE,                       /* APS ACK disabled - 避免ACK等待导致协调器积压 */
          zclFrameData,                   /* payload pointer */
          ZCL_FRAME_SIZE);                /* size of payload */
       
        if (ret != RET_OK) {
            uartPrintf("ZCL data send failed, error code: %d\r\n", ret);
           
            // Handle different error codes
            switch (ret) {
                case RET_INVALID_PARAMETER_1:
                    uartPrintf("Error: Invalid parameter\r\n");
                    break;
                case RET_NO_MEMORY:
                    uartPrintf("Error: Insufficient memory\r\n");
                    break;
                case RET_INVALID_STATE:
                    uartPrintf("Error: Invalid state\r\n");
                    break;
                default:
                    uartPrintf("Unknown error type\r\n");
                    break;
            }
           
            zb_buf_free(param);  /* 发送失败时释放缓冲区 */
        } else {
          uartPrintf("param3: %d\r\n", param);
            // 发送成功,立即释放缓冲区
            // if(param != ZB_BUF_INVALID){
                 zb_buf_free(param);    //发送成功后若不使用该函数则发送7次之后会重启。
            // }
           
        }
      }
    }