/** ****************************************************************************** * File Name : App/app_zigbee.c * Description : Zigbee Application. ****************************************************************************** * @attention * * Copyright (c) 2019-2021 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "app_common.h" #include "app_entry.h" #include "dbg_trace.h" #include "app_zigbee.h" #include "zigbee_interface.h" #include "shci.h" #include "stm_logging.h" #include "app_conf.h" #include "stm32wbxx_core_interface_def.h" #include "zigbee_types.h" #include "stm32_seq.h" #include #include "zcl/zcl.h" /* Private defines -----------------------------------------------------------*/ #define APP_ZIGBEE_STARTUP_FAIL_DELAY 500U #define CHANNEL 14 /* APS specific defines */ #define APS_DEMO_ENDPOINT 1 /* Manufacturer Specific Profiles range [0xc000, 0xffff] */ #define APS_DEMO_PROFILE 0xf000 /* arbitrary */ #define APS_DEMO_CLUSTER_REQ 0x0000 #define APS_DEMO_CLUSTER_RSP 0x0001 /* external definition */ enum ZbStatusCodeT ZbStartupWait(struct ZigBeeT *zb, struct ZbStartupT *config); /* Private function prototypes -----------------------------------------------*/ static void APP_ZIGBEE_StackLayersInit(void); static void APP_ZIGBEE_ConfigEndpoints(void); static void APP_ZIGBEE_NwkForm(void); static void APP_ZIGBEE_App_Init(void); static void APP_ZIGBEE_SW1_Process(void); static void APP_ZIGBEE_TraceError(const char *pMess, uint32_t ErrCode); static void APP_ZIGBEE_CheckWirelessFirmwareInfo(void); static void APP_ZIGBEE_APS_ParseFrame(struct ZbApsdeDataIndT *dataInd); static void APP_ZIGBEE_APS_SendReq(struct ZbApsAddrT *dst); static void APP_ZIGBEE_APS_SendRsp(struct ZbApsAddrT *dst); static void APP_ZIGBEE_APS_Conf_cb(struct ZbApsdeDataConfT *conf, void *arg); static int APP_ZIGBEE_APS_Ind_cb(struct ZbApsdeDataIndT *dataInd, void *cb_arg); static void Wait_Getting_Ack_From_M0(void); static void Receive_Ack_From_M0(void); static void Receive_Notification_From_M0(void); static void APP_ZIGBEE_ProcessNotifyM0ToM4(void); static void APP_ZIGBEE_ProcessRequestM0ToM4(void); void APP_ZIGBEE_ConfigBasicServer(void); /* Defines for Basic Cluster Server */ #define APP_ZIGBEE_MFR_NAME "vh789" #define APP_ZIGBEE_CHIP_NAME "stm32wb55cg" #define APP_ZIGBEE_CHIP_VERSION 0x10 // Cut 1.0 #define APP_ZIGBEE_BOARD_POWER 0x00 // No Power #define APP_ZIGBEE_APP_DATE_CODE "20241021" #define APP_ZIGBEE_APP_BUILD_ID "V1.0-A69" #define APP_ZIGBEE_APP_VERSION 0x10 // Application Version v1.0 #define APP_ZIGBEE_STACK_VERSION 0x10 // Stack Version v1.0 /* Private variables -----------------------------------------------*/ static TL_CmdPacket_t *p_ZIGBEE_otcmdbuffer; static TL_EvtPacket_t *p_ZIGBEE_notif_M0_to_M4; static TL_EvtPacket_t *p_ZIGBEE_request_M0_to_M4; static __IO uint32_t CptReceiveNotifyFromM0 = 0; static __IO uint32_t CptReceiveRequestFromM0 = 0; PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_ZIGBEE_Config_t ZigbeeConfigBuffer; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ZigbeeOtCmdBuffer; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ZigbeeNotifRspEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ZigbeeNotifRequestBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; uint8_t g_ot_notification_allowed = 0U; struct aps_info_t { struct ZbApsFilterT *aps_filter; uint32_t asduHandle; }; struct zigbee_app_info { bool has_init; struct ZigBeeT *zb; enum ZbStatusCodeT join_status; uint32_t join_delay; struct aps_info_t aps_info; }; static struct zigbee_app_info zigbee_app_info; /* Functions Definition ------------------------------------------------------*/ /** * @brief Parse APS frame * @param dataInd: ZigBee APSDE Data Indication frame * @retval None */ static void APP_ZIGBEE_APS_ParseFrame(struct ZbApsdeDataIndT *dataInd){ APP_DBG(" Source nwk addr: 0x%04x", dataInd->src.nwkAddr); APP_DBG(" ProfileID: 0x%02x", dataInd->profileId); APP_DBG(" ClusterID: 0x%02x", dataInd->clusterId); /* Payload */ APP_DBG(" Payload:") for(unsigned int cpt=0; cptasduLength; cpt++){ APP_DBG(" 0x%02x", dataInd->asdu[cpt]); } APP_DBG(" Link quality: %d", dataInd->linkQuality); APP_DBG(" RSSI: %d\n", dataInd->rssi); } /* APP_ZIGBEE_APS_ParseFrame */ /** * @brief ZigBee application APSDE Data Confirmation callback * @param conf: APSDE Data Confirmation * @param arg: passed argument * @retval None */ static void APP_ZIGBEE_APS_Conf_cb(struct ZbApsdeDataConfT *conf, void *arg){ if (conf->status != ZB_STATUS_SUCCESS) { APP_DBG("%s : Error, APS confirm status = 0x%02x", __func__, conf->status); return; } }/* APP_ZIGBEE_APS_Conf_cb */ /** * @brief Send APS request * @param dst: destination address info * @retval None */ static void APP_ZIGBEE_APS_SendReq(struct ZbApsAddrT *dst){ struct ZbApsdeDataReqT aps_req; const uint8_t payload[] = {0x12, 0x34, 0x56}; /* ! This demo app sends a canned payload */ enum ZbStatusCodeT status; memset(&aps_req, 0, sizeof(aps_req)); aps_req.dst = *dst; aps_req.profileId = APS_DEMO_PROFILE; aps_req.clusterId = APS_DEMO_CLUSTER_REQ; aps_req.srcEndpt = APS_DEMO_ENDPOINT; aps_req.asdu = payload; aps_req.asduLength = sizeof(payload); aps_req.asduHandle = zigbee_app_info.aps_info.asduHandle++; aps_req.txOptions |= ZB_APSDE_DATAREQ_TXOPTIONS_SECURITY; /* aps_req.txOptions |= ZB_APSDE_DATAREQ_TXOPTIONS_NWKKEY; */ aps_req.txOptions |= ZB_APSDE_DATAREQ_TXOPTIONS_ACK; APP_DBG("%s : Sending request\n", __func__); status = ZbApsdeDataReqCallback(zigbee_app_info.zb, &aps_req, APP_ZIGBEE_APS_Conf_cb, NULL); if (status != ZB_STATUS_SUCCESS) { APP_DBG("%s : Error, APS send failed for request", __func__); } } /* APP_ZIGBEE_APS_SendReq */ /** * @brief Send APS response * @param dst: destination address info * @retval None */ static void APP_ZIGBEE_APS_SendRsp(struct ZbApsAddrT *dst){ struct ZbApsdeDataReqT aps_req; const uint8_t payload[] = {0xab, 0xcd, 0xef}; /* ! This demo app sends a canned payload */ enum ZbStatusCodeT status; memset(&aps_req, 0, sizeof(aps_req)); aps_req.dst = *dst; aps_req.profileId = APS_DEMO_PROFILE; aps_req.clusterId = APS_DEMO_CLUSTER_RSP; aps_req.srcEndpt = APS_DEMO_ENDPOINT; aps_req.asdu = payload; aps_req.asduLength = sizeof(payload); aps_req.asduHandle = zigbee_app_info.aps_info.asduHandle++; /* Enable packet security */ aps_req.txOptions |= ZB_APSDE_DATAREQ_TXOPTIONS_SECURITY; /* Enable APS ACKing */ aps_req.txOptions |= ZB_APSDE_DATAREQ_TXOPTIONS_ACK; /* Enable ZB_APSDE_DATAREQ_TXOPTIONS_NWKKEY if you just want Network security. * Otherwise APS and NWK security are used. */ /* aps_req.txOptions |= ZB_APSDE_DATAREQ_TXOPTIONS_NWKKEY; */ APP_DBG("%s : Sending response\n", __func__); status = ZbApsdeDataReqCallback(zigbee_app_info.zb, &aps_req, APP_ZIGBEE_APS_Conf_cb, NULL); if (status != ZB_STATUS_SUCCESS) { APP_DBG("%s : Error, APS send failed for response", __func__); } }/* APP_ZIGBEE_APS_SendRsp */ /** * @brief ZigBee application APSDE Data Indication callback * @param dataInd: APSDE Data Indication frame * @param cb_arg: passed argument * @retval None */ static int APP_ZIGBEE_APS_Ind_cb(struct ZbApsdeDataIndT *dataInd, void *cb_arg){ switch (dataInd->clusterId) { case APS_DEMO_CLUSTER_REQ: { APP_DBG("%s : Received request", __func__); APP_ZIGBEE_APS_ParseFrame(dataInd); APP_ZIGBEE_APS_SendRsp(&dataInd->src); break; } case APS_DEMO_CLUSTER_RSP: APP_DBG("%s : Received response", __func__); APP_ZIGBEE_APS_ParseFrame(dataInd); break; default: break; } return ZB_APS_FILTER_CONTINUE; }/* APP_ZIGBEE_APS_Ind_cb */ /** * @brief Zigbee application initialization * @param None * @retval None */ static void APP_ZIGBEE_App_Init(void){ APP_DBG("Init done!\n"); } /** * @brief Zigbee application initialization * @param None * @retval None */ void APP_ZIGBEE_Init(void) { SHCI_CmdStatus_t ZigbeeInitStatus; APP_DBG("APP_ZIGBEE_Init"); /* Check the compatibility with the Coprocessor Wireless Firmware loaded */ APP_ZIGBEE_CheckWirelessFirmwareInfo(); /* Register cmdbuffer */ APP_ZIGBEE_RegisterCmdBuffer(&ZigbeeOtCmdBuffer); /* Init config buffer and call TL_ZIGBEE_Init */ APP_ZIGBEE_TL_INIT(); /* Register task */ /* Create the different tasks */ UTIL_SEQ_RegTask(1U << (uint32_t)CFG_TASK_NOTIFY_FROM_M0_TO_M4, UTIL_SEQ_RFU, APP_ZIGBEE_ProcessNotifyM0ToM4); UTIL_SEQ_RegTask(1U << (uint32_t)CFG_TASK_REQUEST_FROM_M0_TO_M4, UTIL_SEQ_RFU, APP_ZIGBEE_ProcessRequestM0ToM4); /* Task associated with push button SW1 */ UTIL_SEQ_RegTask(1U << CFG_TASK_BUTTON_SW1, UTIL_SEQ_RFU, APP_ZIGBEE_SW1_Process); /* Task associated with network creation process */ UTIL_SEQ_RegTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, UTIL_SEQ_RFU, APP_ZIGBEE_NwkForm); /* Task associated with application init */ UTIL_SEQ_RegTask(1U << CFG_TASK_ZIGBEE_APP_START, UTIL_SEQ_RFU, APP_ZIGBEE_App_Init); /* Start the Zigbee on the CPU2 side */ ZigbeeInitStatus = SHCI_C2_ZIGBEE_Init(); /* Prevent unused argument(s) compilation warning */ UNUSED(ZigbeeInitStatus); /* Initialize Zigbee stack layers */ APP_ZIGBEE_StackLayersInit(); } /* APP_ZIGBEE_Init */ /** * @brief Initialize Zigbee stack layers * @param None * @retval None */ static void APP_ZIGBEE_StackLayersInit(void) { APP_DBG("APP_ZIGBEE_StackLayersInit"); zigbee_app_info.zb = ZbInit(0U, NULL, NULL); assert(zigbee_app_info.zb != NULL); APP_ZIGBEE_ConfigBasicServer(); /* Create the endpoint and cluster(s) */ APP_ZIGBEE_ConfigEndpoints(); BSP_LED_Off(LED_RED); BSP_LED_Off(LED_GREEN); BSP_LED_Off(LED_BLUE); /* Configure the joining parameters */ zigbee_app_info.join_status = (enum ZbStatusCodeT) 0x01; /* init to error status */ zigbee_app_info.join_delay = HAL_GetTick(); /* now */ /* Initialization Complete */ zigbee_app_info.has_init = true; /* run the task */ UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, CFG_SCH_PRIO_0); } /* APP_ZIGBEE_StackLayersInit */ /** * @brief Configure Zigbee application endpoints * @param None * @retval None */ static void APP_ZIGBEE_ConfigEndpoints(void) { struct ZbApsmeAddEndpointReqT req; struct ZbApsmeAddEndpointConfT conf; /* Create APS endpoint for this application */ memset(&req, 0, sizeof(req)); req.profileId = APS_DEMO_PROFILE; req.endpoint = APS_DEMO_ENDPOINT; ZbApsmeAddEndpoint(zigbee_app_info.zb, &req, &conf); assert(conf.status == ZB_STATUS_SUCCESS); /* Create filter to receive APS message */ zigbee_app_info.aps_info.aps_filter = ZbApsFilterEndpointAdd(zigbee_app_info.zb, APS_DEMO_ENDPOINT, APS_DEMO_PROFILE, APP_ZIGBEE_APS_Ind_cb, NULL); assert(zigbee_app_info.aps_info.aps_filter != NULL); } /* APP_ZIGBEE_ConfigEndpoints */ void APP_ZIGBEE_ConfigBasicServer(void) { static struct ZbZclBasicServerDefaults stBasicServerDefaults; /* Initialize Basic Server Cluster 'defaults' information */ memset( &stBasicServerDefaults, 0x00, sizeof(stBasicServerDefaults) ); stBasicServerDefaults.mfr_name[0] = sizeof( APP_ZIGBEE_MFR_NAME ); memcpy( &stBasicServerDefaults.mfr_name[1], APP_ZIGBEE_MFR_NAME, sizeof( APP_ZIGBEE_MFR_NAME ) ); stBasicServerDefaults.model_name[0] = sizeof( APP_ZIGBEE_CHIP_NAME ); memcpy( &stBasicServerDefaults.model_name[1], APP_ZIGBEE_CHIP_NAME, sizeof( APP_ZIGBEE_CHIP_NAME ) ); stBasicServerDefaults.date_code[0] = sizeof( APP_ZIGBEE_APP_DATE_CODE ); memcpy( &stBasicServerDefaults.date_code[1], APP_ZIGBEE_APP_DATE_CODE, sizeof( APP_ZIGBEE_APP_DATE_CODE ) ); stBasicServerDefaults.sw_build_id[0] = sizeof( APP_ZIGBEE_APP_BUILD_ID ); memcpy( &stBasicServerDefaults.sw_build_id[1], APP_ZIGBEE_APP_BUILD_ID, sizeof( APP_ZIGBEE_APP_BUILD_ID ) ); /* Version are on 8 bits : 3 bits for Major version and 5 bits for Minor version */ stBasicServerDefaults.app_version = (uint8_t)( ( APP_ZIGBEE_APP_VERSION & 0x70u ) << 1u ) | ( APP_ZIGBEE_APP_VERSION & 0x0Fu ); stBasicServerDefaults.stack_version = (uint8_t)( ( APP_ZIGBEE_STACK_VERSION & 0x70u ) << 1u ) | ( APP_ZIGBEE_STACK_VERSION & 0x0Fu ); stBasicServerDefaults.hw_version = (uint8_t)( ( APP_ZIGBEE_CHIP_VERSION & 0x70u ) << 1u ) | ( APP_ZIGBEE_CHIP_VERSION & 0x0Fu ); stBasicServerDefaults.power_source = APP_ZIGBEE_BOARD_POWER; /* Configure default Basic Server */ ZbZclBasicServerConfigDefaults( zigbee_app_info.zb , &stBasicServerDefaults ); } /** * @brief Handle Zigbee network forming and joining * @param None * @retval None */ static void APP_ZIGBEE_NwkForm(void) { if ((zigbee_app_info.join_status != ZB_STATUS_SUCCESS) && (HAL_GetTick() >= zigbee_app_info.join_delay)) { struct ZbStartupT config; enum ZbStatusCodeT status; /* Configure Zigbee Logging (only need to do this once, but this is a good place to put it) */ ZbSetLogging(zigbee_app_info.zb, ZB_LOG_MASK_LEVEL_5, NULL); /* Attempt to join a zigbee network */ ZbStartupConfigGetProDefaults(&config); /* Set the centralized network */ APP_DBG("Network config : APP_STARTUP_CENTRALIZED_ROUTER"); config.startupControl = ZbStartTypeJoin; /* Using the default HA preconfigured Link Key */ memcpy(config.security.preconfiguredLinkKey, sec_key_ha, ZB_SEC_KEYSIZE); config.channelList.count = 1; config.channelList.list[0].page = 0; config.channelList.list[0].channelMask = 1 << CHANNEL; /*Channel in use */ /* Using ZbStartupWait (blocking) here instead of ZbStartup, in order to demonstrate how to do * a blocking call on the M4. */ status = ZbStartupWait(zigbee_app_info.zb, &config); APP_DBG("ZbStartup Callback (status = 0x%02x)", status); zigbee_app_info.join_status = status; if (status == ZB_STATUS_SUCCESS) { zigbee_app_info.join_delay = 0U; BSP_LED_On(LED_BLUE); } else { APP_DBG("Startup failed, re-attempting to form a network after a short delay (%d ms)", APP_ZIGBEE_STARTUP_FAIL_DELAY); zigbee_app_info.join_delay = HAL_GetTick() + APP_ZIGBEE_STARTUP_FAIL_DELAY; } } /* If Network forming/joining was not successful reschedule the current task to retry the process */ if (zigbee_app_info.join_status != ZB_STATUS_SUCCESS) { UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, CFG_SCH_PRIO_0); } else { /* Starting application init task */ UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_APP_START, CFG_SCH_PRIO_0); } } /* APP_ZIGBEE_NwkForm */ /************************************************************* * ZbStartupWait Blocking Call *************************************************************/ struct ZbStartupWaitInfo { bool active; enum ZbStatusCodeT status; }; static void ZbStartupWaitCb(enum ZbStatusCodeT status, void *cb_arg) { struct ZbStartupWaitInfo *info = cb_arg; info->status = status; info->active = false; UTIL_SEQ_SetEvt(EVENT_ZIGBEE_STARTUP_ENDED); } /* ZbStartupWaitCb */ enum ZbStatusCodeT ZbStartupWait(struct ZigBeeT *zb, struct ZbStartupT *config) { struct ZbStartupWaitInfo *info; enum ZbStatusCodeT status; info = malloc(sizeof(struct ZbStartupWaitInfo)); if (info == NULL) { return ZB_STATUS_ALLOC_FAIL; } memset(info, 0, sizeof(struct ZbStartupWaitInfo)); info->active = true; status = ZbStartup(zb, config, ZbStartupWaitCb, info); if (status != ZB_STATUS_SUCCESS) { free(info); return status; } UTIL_SEQ_WaitEvt(EVENT_ZIGBEE_STARTUP_ENDED); status = info->status; free(info); return status; } /* ZbStartupWait */ /** * @brief Trace the error or the warning reported. * @param ErrId : * @param ErrCode * @retval None */ void APP_ZIGBEE_Error(uint32_t ErrId, uint32_t ErrCode) { switch (ErrId) { default: APP_ZIGBEE_TraceError("ERROR Unknown ", 0); break; } } /* APP_ZIGBEE_Error */ /************************************************************* * * LOCAL FUNCTIONS * *************************************************************/ /** * @brief Warn the user that an error has occurred.In this case, * the LEDs on the Board will start blinking. * * @param pMess : Message associated to the error. * @param ErrCode: Error code associated to the module (Zigbee or other module if any) * @retval None */ static void APP_ZIGBEE_TraceError(const char *pMess, uint32_t ErrCode) { APP_DBG("**** Fatal error = %s (Err = %d)", pMess, ErrCode); while (1U == 1U) { BSP_LED_Toggle(LED1); HAL_Delay(500U); BSP_LED_Toggle(LED2); HAL_Delay(500U); BSP_LED_Toggle(LED3); HAL_Delay(500U); } } /* APP_ZIGBEE_TraceError */ /** * @brief Check if the Coprocessor Wireless Firmware loaded supports Zigbee * and display associated information * @param None * @retval None */ static void APP_ZIGBEE_CheckWirelessFirmwareInfo(void) { WirelessFwInfo_t wireless_info_instance; WirelessFwInfo_t *p_wireless_info = &wireless_info_instance; if (SHCI_GetWirelessFwInfo(p_wireless_info) != SHCI_Success) { APP_ZIGBEE_Error((uint32_t)ERR_ZIGBEE_CHECK_WIRELESS, (uint32_t)ERR_INTERFACE_FATAL); } else { APP_DBG("**********************************************************"); APP_DBG("WIRELESS COPROCESSOR FW:"); /* Print version */ APP_DBG("VERSION ID = %d.%d.%d", p_wireless_info->VersionMajor, p_wireless_info->VersionMinor, p_wireless_info->VersionSub); switch (p_wireless_info->StackType) { case INFO_STACK_TYPE_ZIGBEE_FFD: APP_DBG("FW Type : FFD Zigbee stack"); break; case INFO_STACK_TYPE_ZIGBEE_RFD: APP_DBG("FW Type : RFD Zigbee stack"); break; default: /* No Zigbee device supported ! */ APP_ZIGBEE_Error((uint32_t)ERR_ZIGBEE_CHECK_WIRELESS, (uint32_t)ERR_INTERFACE_FATAL); break; } // print the application name char* __PathProject__ =(strstr(__FILE__, "Zigbee") ? strstr(__FILE__, "Zigbee") + 7 : __FILE__); char *del; if ( (strchr(__FILE__, '/')) == NULL) {del = strchr(__PathProject__, '\\');} else {del = strchr(__PathProject__, '/');} int index = (int) (del - __PathProject__); APP_DBG("Application flashed: %*.*s",index,index,__PathProject__); //print channel APP_DBG("Channel used: %d", CHANNEL); //print Link Key APP_DBG("Link Key: %.16s", sec_key_ha); //print Link Key value hex char Z09_LL_string[ZB_SEC_KEYSIZE*3+1]; Z09_LL_string[0]=0; for(int str_index=0; str_index < ZB_SEC_KEYSIZE; str_index++) { sprintf(&Z09_LL_string[str_index*3],"%02x ",sec_key_ha[str_index]); } APP_DBG("Link Key value: %s",Z09_LL_string); APP_DBG("**********************************************************"); } } /* APP_ZIGBEE_CheckWirelessFirmwareInfo */ /** * @brief Button 1 callback * @param None * @retval None */ static void APP_ZIGBEE_SW1_Process(void){ struct ZbApsAddrT dst; uint64_t epid = 0U; if(zigbee_app_info.zb == NULL){ return; } /* Check if the router joined the network */ if (ZbNwkGet(zigbee_app_info.zb, ZB_NWK_NIB_ID_ExtendedPanId, &epid, sizeof(epid)) != ZB_STATUS_SUCCESS) { return; } if (epid == 0U) { return; } /* Send a request */ memset(&dst, 0, sizeof(dst)); dst.mode = ZB_APSDE_ADDRMODE_SHORT; dst.endpoint = APS_DEMO_ENDPOINT; dst.nwkAddr = 0x0000; APP_ZIGBEE_APS_SendReq(&dst); } /* APP_ZIGBEE_SW1_Process */ /************************************************************* * * WRAP FUNCTIONS * *************************************************************/ void APP_ZIGBEE_RegisterCmdBuffer(TL_CmdPacket_t *p_buffer) { p_ZIGBEE_otcmdbuffer = p_buffer; } /* APP_ZIGBEE_RegisterCmdBuffer */ Zigbee_Cmd_Request_t * ZIGBEE_Get_OTCmdPayloadBuffer(void) { return (Zigbee_Cmd_Request_t *)p_ZIGBEE_otcmdbuffer->cmdserial.cmd.payload; } /* ZIGBEE_Get_OTCmdPayloadBuffer */ Zigbee_Cmd_Request_t * ZIGBEE_Get_OTCmdRspPayloadBuffer(void) { return (Zigbee_Cmd_Request_t *)((TL_EvtPacket_t *)p_ZIGBEE_otcmdbuffer)->evtserial.evt.payload; } /* ZIGBEE_Get_OTCmdRspPayloadBuffer */ Zigbee_Cmd_Request_t * ZIGBEE_Get_NotificationPayloadBuffer(void) { return (Zigbee_Cmd_Request_t *)(p_ZIGBEE_notif_M0_to_M4)->evtserial.evt.payload; } /* ZIGBEE_Get_NotificationPayloadBuffer */ Zigbee_Cmd_Request_t * ZIGBEE_Get_M0RequestPayloadBuffer(void) { return (Zigbee_Cmd_Request_t *)(p_ZIGBEE_request_M0_to_M4)->evtserial.evt.payload; } /** * @brief This function is used to transfer the commands from the M4 to the M0. * * @param None * @return None */ void ZIGBEE_CmdTransfer(void) { Zigbee_Cmd_Request_t *cmd_req = (Zigbee_Cmd_Request_t *)p_ZIGBEE_otcmdbuffer->cmdserial.cmd.payload; /* Zigbee OT command cmdcode range 0x280 .. 0x3DF = 352 */ p_ZIGBEE_otcmdbuffer->cmdserial.cmd.cmdcode = 0x280U; /* Size = otCmdBuffer->Size (Number of OT cmd arguments : 1 arg = 32bits so multiply by 4 to get size in bytes) * + ID (4 bytes) + Size (4 bytes) */ p_ZIGBEE_otcmdbuffer->cmdserial.cmd.plen = 8U + (cmd_req->Size * 4U); TL_ZIGBEE_SendM4RequestToM0(); /* Wait completion of cmd */ Wait_Getting_Ack_From_M0(); } /* ZIGBEE_CmdTransfer */ /** * @brief This function is used to transfer the commands from the M4 to the M0 with notification * * @param None * @return None */ void ZIGBEE_CmdTransferWithNotif(void) { g_ot_notification_allowed = 1; ZIGBEE_CmdTransfer(); } /** * @brief This function is called when the M0+ acknowledge the fact that it has received a Cmd * * * @param Otbuffer : a pointer to TL_EvtPacket_t * @return None */ void TL_ZIGBEE_CmdEvtReceived(TL_EvtPacket_t *Otbuffer) { /* Prevent unused argument(s) compilation warning */ UNUSED(Otbuffer); Receive_Ack_From_M0(); } /* TL_ZIGBEE_CmdEvtReceived */ /** * @brief This function is called when notification from M0+ is received. * * @param Notbuffer : a pointer to TL_EvtPacket_t * @return None */ void TL_ZIGBEE_NotReceived(TL_EvtPacket_t *Notbuffer) { p_ZIGBEE_notif_M0_to_M4 = Notbuffer; Receive_Notification_From_M0(); } /* TL_ZIGBEE_NotReceived */ /** * @brief This function is called before sending any ot command to the M0 * core. The purpose of this function is to be able to check if * there are no notifications coming from the M0 core which are * pending before sending a new ot command. * @param None * @retval None */ void Pre_ZigbeeCmdProcessing(void) { UTIL_SEQ_WaitEvt(EVENT_SYNCHRO_BYPASS_IDLE); } /* Pre_ZigbeeCmdProcessing */ /** * @brief This function waits for getting an acknowledgment from the M0. * * @param None * @retval None */ static void Wait_Getting_Ack_From_M0(void) { UTIL_SEQ_WaitEvt(EVENT_ACK_FROM_M0_EVT); } /* Wait_Getting_Ack_From_M0 */ /** * @brief Receive an acknowledgment from the M0+ core. * Each command send by the M4 to the M0 are acknowledged. * This function is called under interrupt. * @param None * @retval None */ static void Receive_Ack_From_M0(void) { UTIL_SEQ_SetEvt(EVENT_ACK_FROM_M0_EVT); } /* Receive_Ack_From_M0 */ /** * @brief Receive a notification from the M0+ through the IPCC. * This function is called under interrupt. * @param None * @retval None */ static void Receive_Notification_From_M0(void) { CptReceiveNotifyFromM0++; UTIL_SEQ_SetTask(1U << (uint32_t)CFG_TASK_NOTIFY_FROM_M0_TO_M4, CFG_SCH_PRIO_0); } /** * @brief This function is called when a request from M0+ is received. * * @param Notbuffer : a pointer to TL_EvtPacket_t * @return None */ void TL_ZIGBEE_M0RequestReceived(TL_EvtPacket_t *Reqbuffer) { p_ZIGBEE_request_M0_to_M4 = Reqbuffer; CptReceiveRequestFromM0++; UTIL_SEQ_SetTask(1U << (uint32_t)CFG_TASK_REQUEST_FROM_M0_TO_M4, CFG_SCH_PRIO_0); } /** * @brief Perform initialization of TL for Zigbee. * @param None * @retval None */ void APP_ZIGBEE_TL_INIT(void) { ZigbeeConfigBuffer.p_ZigbeeOtCmdRspBuffer = (uint8_t *)&ZigbeeOtCmdBuffer; ZigbeeConfigBuffer.p_ZigbeeNotAckBuffer = (uint8_t *)ZigbeeNotifRspEvtBuffer; ZigbeeConfigBuffer.p_ZigbeeNotifRequestBuffer = (uint8_t *)ZigbeeNotifRequestBuffer; TL_ZIGBEE_Init(&ZigbeeConfigBuffer); } /** * @brief Process the messages coming from the M0. * @param None * @retval None */ static void APP_ZIGBEE_ProcessNotifyM0ToM4(void) { if (CptReceiveNotifyFromM0 != 0) { /* Reset counter */ CptReceiveNotifyFromM0 = 0; Zigbee_CallBackProcessing(); } } /** * @brief Process the requests coming from the M0. * @param * @return */ static void APP_ZIGBEE_ProcessRequestM0ToM4(void) { if (CptReceiveRequestFromM0 != 0) { CptReceiveRequestFromM0 = 0; Zigbee_M0RequestProcessing(); } }