您好!
我正在使用简单的网状节点示例、我想实现一项配置器件并在不使用 UART 接口的情况下实现器件之间通信的任务。 回调函数除外、但当我尝试通过按下按钮来打开另一个设备的 LED 时、它会切换自己的 LED、 因此、我正在使用的两个器件之间没有通信、并且每个器件都在不同的网络上、这两个器件无法检测到异常。 使用 BLE 扫描仪可以检测到设备。 我还遵循了 BLE 网状网络基础教程、以便创建我自己的模型。 要启用设备之间的识别,缺少什么? 我已在两款器件上启用静态配置、就像在原始简单网状节点示例中一样。
此致、
Alexandra
/****************************************************************************** @file static_prov.c @brief This file contains static provisioning configurations and performance. Group: WCS, BTS Target Device: cc13xx_cc26xx ****************************************************************************** Copyright (c) 2013-2022, Texas Instruments Incorporated All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Texas Instruments Incorporated nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************** *****************************************************************************/ #ifdef USE_STATIC_PROVISIONING /********************************************************************* * INCLUDES */ #include "static_prov.h" #include "mesh_erpc_wrapper.h" #include "ti_device_composition.h" #include <zephyr.h> #include <sys/printk.h> #include <settings/settings.h> #include <bluetooth/bluetooth.h> #include <bluetooth/mesh.h> /********************************************************************* * MACROS */ #define MOD_LF 0x0000 #define GROUP_ADDR 0xc000 /********************************************************************* * CONSTANTS */ /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ /********************************************************************* * LOCAL VARIABLES */ static const uint16_t net_idx; static const uint32_t iv_index; static uint8_t prov_flags = 0; static const uint8_t net_key[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; static const uint8_t dev_key[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; static const uint8_t app_key[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; /********************************************************************* * LOCAL FUNCTIONS */ static void MeshApp_provConfigure(uint16_t addr, uint16_t app_idx); /********************************************************************* * EXTERN FUNCTIONS */ /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn MeshApp_static_provisioning * * @brief Perform Static Provisioning by calling bt_mesh_provision * and MeshApp_provConfigure * * @param addr * @param app_idx */ int MeshApp_static_provisioning(uint16_t addr, uint16_t app_idx) { int status; status = bt_mesh_provision(net_key, net_idx, prov_flags, iv_index, addr, dev_key); if (status) { return status; } MeshApp_provConfigure(addr, app_idx); return status; } /********************************************************************* * @fn MeshApp_provConfigure * * @brief Configure the Mesh Node * * @param addr * @param app_idx */ static void MeshApp_provConfigure(uint16_t addr, uint16_t app_idx) { /* Add Application Key */ bt_mesh_cfg_app_key_add_wrapper(net_idx, addr, net_idx, app_idx, app_key); /* Bind to vendor model */ bt_mesh_cfg_mod_app_bind_vnd_wrapper(net_idx, addr, addr, app_idx, MOD_LF, CONFIG_BT_COMPANY_ID); /* Bind to Health model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_HEALTH_SRV); /* Bind to Generic OnOff server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_SRV); /* When using static provisioning, the loopback buffer is used * when the device sends messages. * The amount of the loopback buffers is determined by * CONFIG_BT_MESH_LOOPBACK_BUFS which is defined in autoconf.h. * Sleep is needed for the loopback buffers to be freed. */ k_sleep(K_MSEC(100)); /* Bind to vendor model bt_mesh_cfg_mod_app_bind_vnd Input Parameter Deep-dive net_idx: Pass in the network index addr: Address of the node elem_addr: Address of the element of the node. Here we refer to the second element, so we add 1. mod_app_idx: Application Key Index mod_id: Model ID. Here we set 0x1234 to match our Model ID in SysConfig. cid: Company ID status: Not needed */ bt_mesh_cfg_mod_app_bind_vnd(net_idx, addr, addr+1, app_idx, 0x1234, CONFIG_BT_COMPANY_ID, NULL); /* Bind to Generic OnOff client model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_ONOFF_CLI); /* Bind to Generic Level server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_LEVEL_SRV); /* Bind to Generic Level client model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_LEVEL_CLI); k_sleep(K_MSEC(100)); /* Bind to Generic Transition Time server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV); /* Bind to Generic Transition Time client model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI); /* Bind to Generic Power OnOff server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV); k_sleep(K_MSEC(100)); /* Bind to Generic Power OnOff client model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI); /* Bind to Generic Power OnOff Setup server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV); /* Bind to Generic Battery server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_BATTERY_SRV); k_sleep(K_MSEC(100)); /* Bind to Generic Battery client model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_GEN_BATTERY_CLI); /* Bind to Sensor server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_SENSOR_SRV); /* Bind to Sensor client model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_SENSOR_CLI); k_sleep(K_MSEC(100)); /* Bind to Sensor setup server model */ bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_SENSOR_SETUP_SRV); /* Add model subscription */ bt_mesh_cfg_mod_sub_add_vnd_wrapper(net_idx, addr, addr, GROUP_ADDR, MOD_LF, CONFIG_BT_COMPANY_ID); /* Add model subscription */ bt_mesh_cfg_mod_sub_add_vnd(net_idx, addr, addr+1, GROUP_ADDR, 0x1234, CONFIG_BT_COMPANY_ID, NULL); } #endif // USE_STATIC_PROVISIONING
/****************************************************************************** * * @file simple_mesh_node.c @brief This file contains the simple_peripheral_and_mesh sample application for use with the CC2652 Bluetooth Low Energy Protocol Stack. Group: WCS, BTS Target Device: cc13xx_cc26xx ****************************************************************************** Copyright (c) 2013-2022, Texas Instruments Incorporated All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Texas Instruments Incorporated nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************** *****************************************************************************/ /********************************************************************* * INCLUDES */ #include <string.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Clock.h> #include <ti/sysbios/knl/Event.h> #include <ti/sysbios/knl/Queue.h> #include <ti/display/Display.h> #include "autoconf.h" #define ADD_SENSOR_MODELS #if !(defined __TI_COMPILER_VERSION__) && !(defined __GNUC__) #include <intrinsics.h> #endif #include <ti/drivers/utils/List.h> #include "util.h" #include <bcomdef.h> #include "ble_stack_api.h" #include <devinfoservice.h> #include <simple_gatt_profile.h> #ifdef USE_RCOSC #include <rcosc_calibration.h> #endif //USE_RCOSC #include <ti_drivers_config.h> #include <board_key.h> #include <menu/two_btn_menu.h> #include "simple_mesh_node.h" #include "simple_mesh_node_menu.h" #include "ti_ble_config.h" #include "ti_device_composition.h" #if defined(OAD_SUPPORT) #include "oad_app_support.h" #endif #include <zephyr.h> #include <sys/printk.h> #include <settings/settings.h> #include <bluetooth/bluetooth.h> #include <bluetooth/mesh.h> #include <bt_le_porting_layer.h> #ifdef USE_STATIC_PROVISIONING #include "static_prov.h" #endif #include "generic_models.h" #include "sensor_models.h" #include "sensor_temperature8.h" #include "mesh_erpc_wrapper.h" /********************************************************************* * MACROS */ /********************************************************************* * CONSTANTS */ // How often to perform periodic event (in ms) #define BLEAPP_PERIODIC_EVT_PERIOD 2000 // Task configuration #define BLEAPP_TASK_PRIORITY 3 #ifndef BLEAPP_TASK_STACK_SIZE #define BLEAPP_TASK_STACK_SIZE 2248 #endif // Application events #define BLEAPP_EVT_CHAR_CHANGE 1 #define BLEAPP_EVT_KEY_CHANGE 2 #define BLEAPP_EVT_ADV 3 #define BLEAPP_EVT_PAIRING_STATE 4 #define BLEAPP_EVT_PASSCODE_NEEDED 5 #define BLEAPP_EVT_PERIODIC 6 #define BLEAPP_EVT_READ_RPA 7 #define BLEAPP_EVT_SEND_PARAM_UPDATE 8 #define BLEAPP_EVT_CONN 9 #define BLEAPP_EVT_INSUFFICIENT_MEM 10 #define BLEAPP_EVT_ADV_REPORT 11 #define BLEAPP_EVT_SCAN_ENABLED 12 #define BLEAPP_EVT_SCAN_DISABLED 13 #define MESHAPP_EVT_ADV 14 #define MESHAPP_EVT_GATT_WRT 15 #define BLEAPP_EVT_STACK_CALLBACK 16 #define OADAPP_EVT_CALLBACK 17 #define OADAPP_EVT_RESET 18 // For storing the active connections #define SP_RSSI_TRACK_CHNLS 1 // Max possible channels can be GAP_BONDINGS_MAX #define SP_MAX_RSSI_STORE_DEPTH 5 #define SP_INVALID_HANDLE 0xFFFF #define RSSI_2M_THRSHLD -30 #define RSSI_1M_THRSHLD -40 #define RSSI_S2_THRSHLD -50 #define RSSI_S8_THRSHLD -60 #define SP_PHY_NONE LL_PHY_NONE // No PHY set #define AUTO_PHY_UPDATE 0xFF // Spin if the expression is not true #define BLEAPP_ASSERT(expr) if (!(expr)) bleApp_spin(); // address string length is an ascii character for each digit + #define SMN_ADDR_STR_SIZE 15 #define APP_QUEUE_EVT UTIL_QUEUE_EVENT_ID // Event_Id_30 #define EVENT_PEND_FOREVER 0xfffffffful /********************************************************************* * TYPEDEFS */ // App event passed from stack modules. This type is defined by the application // since it can queue events to itself however it wants. typedef struct { uint8_t event; // event type void *pData; // pointer to message } appEvt_t; // Container to store passcode data when passing from gapbondmgr callback // to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h // header file for more information on each parameter. typedef struct { uint8_t state; uint16_t connHandle; uint8_t status; } appPairStateData_t; // Container to store passcode data when passing from gapbondmgr callback // to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h // header file for more information on each parameter. typedef struct { uint8_t deviceAddr[B_ADDR_LEN]; uint16_t connHandle; uint8_t uiInputs; uint8_t uiOutputs; uint32_t numComparison; } appPasscodeData_t; // Container to store advertising event data when passing from advertising // callback to app event. See the respective event in GapAdvScan_Event_IDs // in gap_advertiser.h for the type that pBuf should be cast to. typedef struct { uint32_t event; void *pBuf; } appGapAdvEventData_t; // Container to store information from clock expiration using a flexible array // since data is not always needed typedef struct { uint8_t event; uint8_t data[]; } appClockEventData_t; // Scanned device information record typedef struct { uint8_t addrType; // Peer Device's Address Type uint8_t addr[B_ADDR_LEN]; // Peer Device Address } scanRec_t; // Container to store all scan callback params typedef struct { uint32_t evt; void* pMsg; uintptr_t arg; } scanCbData_t; #ifdef ADD_SIMPLE_PERIPHERAL // List element for parameter update and PHY command status lists typedef struct { List_Elem elem; uint16_t connHandle; } spConnHandleEntry_t; // Connected device information typedef struct { uint16_t connHandle; // Connection Handle appClockEventData_t* pParamUpdateEventData; Clock_Struct* pUpdateClock; // pointer to clock struct int8_t rssiArr[SP_MAX_RSSI_STORE_DEPTH]; uint8_t rssiCntr; int8_t rssiAvg; bool phyCngRq; // Set to true if PHY change request is in progress uint8_t currPhy; uint8_t rqPhy; uint8_t phyRqFailCnt; // PHY change request count bool isAutoPHYEnable; // Flag to indicate auto phy change } spConnRec_t; #endif // ADD_SIMPLE_PERIPHERAL /********************************************************************* * GLOBAL VARIABLES */ // Display Interface Display_Handle dispHandle = NULL; // Task configuration Task_Struct appTask; #if defined __TI_COMPILER_VERSION__ #pragma DATA_ALIGN(appTaskStack, 8) #else #pragma data_alignment=8 #endif uint8_t appTaskStack[BLEAPP_TASK_STACK_SIZE]; #define BLEAPP_EVT_EVENT_MAX 19 char *appEventStrings[] = { "BLEAPP_ZERO ", "BLEAPP_EVT_CHAR_CHANGE ", "BLEAPP_EVT_KEY_CHANGE ", "BLEAPP_EVT_ADV ", "BLEAPP_EVT_PAIRING_STATE ", "BLEAPP_EVT_PASSCODE_NEEDED ", "BLEAPP_EVT_PERIODIC ", "BLEAPP_EVT_READ_RPA ", "BLEAPP_EVT_SEND_PARAM_UPDATE", "BLEAPP_EVT_CONN ", "BLEAPP_EVT_INSUFFICIENT_MEM ", "BLEAPP_EVT_ADV_REPORT ", "BLEAPP_EVT_SCAN_ENABLED ", "BLEAPP_EVT_SCAN_DISABLED ", "MESHAPP_EVT_ADV ", "MESHAPP_EVT_GATT_WRT ", "BLEAPP_EVT_STACK_CALLBACK ", "OADAPP_EVT_CALLBACK ", "OADAPP_EVT_RESET ", }; /********************************************************************* * LOCAL VARIABLES */ // Entity ID globally used to check for source and/or destination of messages bleStack_entityId_t appSelfEntity; bleStack_entityId_t meshAppSelfEntity; //extern in bt.c static Event_Handle appSyncEvent; // Queue object used for app messages static Queue_Struct appMsgQueue; static Queue_Handle appMsgQueueHandle; // Clock instance for internal periodic events. Only one is needed since // GattServApp will handle notifying all connected GATT clients static Clock_Struct clkPeriodic; // Clock instance for RPA read events. static Clock_Struct clkRpaRead; // Memory to pass periodic event ID to clock handler appClockEventData_t argPeriodic = { .event = BLEAPP_EVT_PERIODIC }; // Memory to pass RPA read event ID to clock handler appClockEventData_t argRpaRead = { .event = BLEAPP_EVT_READ_RPA }; #ifdef ADD_SIMPLE_PERIPHERAL // Per-handle connection info spConnRec_t connList[MAX_NUM_BLE_CONNS]; // Current connection handle as chosen by menu static uint16_t menuConnHandle = LINKDB_CONNHANDLE_INVALID; // List to store connection handles for set phy command status's static List_List setPhyCommStatList; // List to store connection handles for queued param updates static List_List paramUpdateList; // Auto connect Disabled/Enabled {0 - Disabled, 1- Group A , 2-Group B, ...} uint8_t autoConnect = AUTOCONNECT_DISABLE; // Advertising handles static uint8 advHandle1; #ifdef SECOND_ADV_SET static uint8 advHandle2; #endif /* SECOND_ADV_SET */ #endif // ADD_SIMPLE_PERIPHERAL // Address mode static GAP_Addr_Modes_t addrMode = ADDRMODE_PUBLIC;//DEFAULT_ADDRESS_MODE; #ifdef ADD_SIMPLE_PERIPHERAL // Current Random Private Address static uint8 rpa[B_ADDR_LEN] = {0}; #endif // ADD_SIMPLE_PERIPHERAL #ifdef USE_STATIC_PROVISIONING uint16_t mesh_own_addr = DEVICE_OWN_ADDRESS; #else uint16_t mesh_own_addr = 1; #endif int advCb_count = 0; int scanCb_count = 0; int scanCb_beaconCount = 0; int scanCb_msgCount = 0; int scanCb_provCount = 0; #ifdef CONFIG_BT_MESH_PROXY static uint8_t meshScanData[] = "SimpleMeshNode"; #endif // Used for save and restore the default device UUID uint8_t defaultUUID[UUID_MAX_LEN]; /********************************************************************* * LOCAL FUNCTIONS */ static void bleApp_init( void ); static void bleApp_taskFxn(UArg a0, UArg a1); static void bleApp_processAppMsg(appEvt_t *pMsg); static uint8_t bleApp_processStackMsg(bleStack_msgHdt_t *pMsg); static uint8_t bleApp_processGATTMsg(gattMsgEvent_t *pMsg); static void bleApp_processGapMessage(gapEventHdr_t *pMsg); #ifdef USE_APP_MENU static void bleApp_handleKeys(uint8_t keys); #endif static void bleApp_keyChangeHandler(uint8_t keys); static status_t bleApp_enqueueMsg(uint8_t event, void *pData); static void bleApp_performPeriodicTask(void); static void bleApp_clockHandler(UArg arg); static void bleApp_passcodeCB(uint8_t *pDeviceAddr, uint16_t connHandle, uint8_t uiInputs, uint8_t uiOutputs, uint32_t numComparison); static void bleApp_pairStateCb(uint16_t connHandle, uint8_t state, uint8_t status); static void meshApp_processAdvEvent(appGapAdvEventData_t *pEventData); #ifdef ADD_SIMPLE_PERIPHERAL static void bleApp_processAdvEvent(appGapAdvEventData_t *pEventData); static void bleApp_charValueChangeCB(uint8_t paramId); static void bleApp_processCharValueChangeEvt(uint8_t paramId); static void SimplePeripheral_advCallback(uint32_t event, void *pBuf, uintptr_t arg); static void SimplePeripheral_updateRPA(void); static void bleApp_processPairState(appPairStateData_t *pPairState); static void bleApp_processPasscode(appPasscodeData_t *pPasscodeData); static void bleApp_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg); static void SimplePeripheral_initPHYRSSIArray(void); static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg); static uint8_t SimplePeripheral_addConn(uint16_t connHandle); static uint8_t SimplePeripheral_getConnIndex(uint16_t connHandle); static uint8_t SimplePeripheral_removeConn(uint16_t connHandle); static void bleApp_processParamUpdate(uint16_t connHandle); static status_t SimplePeripheral_startAutoPhyChange(uint16_t connHandle); static status_t SimplePeripheral_stopAutoPhyChange(uint16_t connHandle); static status_t SimplePeripheral_setPhy(uint16_t connHandle, uint8_t allPhys, uint8_t txPhy, uint8_t rxPhy, uint16_t phyOpts); static uint8_t SimplePeripheral_clearConnListEntry(uint16_t connHandle); void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport); static void bleApp_processConnEvt(Gap_ConnEventRpt_t *pReport); static bStatus_t SimplePeripheral_initAdvSet(pfnGapCB_t advCallback, uint8_t * const advHandle, GapAdv_params_t * const advParams, uint8_t advData[], const int advDataLen, uint8_t scanRespData[], const int scanRespDataLen); #ifdef PTM_MODE void PTM_init(bleStack_entityId_t appSelfEntity); void PTM_handle_hci_event(uint8_t *pMsg); #endif // PTM_MODE #endif // ADD_SIMPLE_PERIPHERAL uint8_t bleApp_processStackMsgCB(uint8_t event, uint8_t *pMsg); /* Mesh profile */ int generic_models_extensions(void); int MeshApp_init(uint16_t addr, uint8_t prov_type); int MeshApp_unprovisioned_beacon(void); /* Mesh Callbacks */ #ifdef USE_APP_MENU #ifdef CONFIG_BT_MESH_LOW_POWER static void meshApp_lpn_friendshipEstablished(uint16_t net_idx, uint16_t friend_addr, uint8_t queue_size, uint8_t recv_window); static void meshApp_lpn_friendshipTerminated(uint16_t net_idx, uint16_t friend_addr); static void meshApp_lpnPolled(uint16_t net_idx, uint16_t friend_addr, bool retry); #endif /* CONFIG_BT_MESH_LOW_POWER */ static void meshApp_hbRecv(const struct bt_mesh_hb_sub *sub, uint8_t hops, uint16_t feat); static void meshApp_hb_subEnd(const struct bt_mesh_hb_sub *sub); #ifdef CONFIG_BT_MESH_FRIEND static void meshApp_friend_friendshipEstablished(uint16_t net_idx, uint16_t lpn_addr, uint8_t recv_delay, uint32_t polltimeout); static void meshApp_friend_friendshipTerminated(uint16_t net_idx, uint16_t lpn_addr); #endif /* CONFIG_BT_MESH_FRIEND */ #endif /* USE_APP_MENU */ /********************************************************************* * EXTERN FUNCTIONS */ extern void AssertHandler(uint8 assertCause, uint8 assertSubcause); extern void mesh_portingLayer_scanCB(uint32_t evt, void* pMsg, uintptr_t arg); extern void mesh_portingLayer_advCB(uint32_t event, void *pBuf); extern int k_sys_work_q_init(void *dev); #ifdef CONFIG_BT_MESH_PROXY extern Event_Handle workQThreadSyncEvent; #endif #ifdef MESH_ERPC extern void eRpcMesh_createTask(); // ERPC thread entity ID globally used to check for source and/or // destination of messages bleStack_entityId_t erpcThreadSelfEntity; // eRPC thread // ERPC thread event globally used to post local events and pend on // system and local events Event_Handle erpcThreadSyncEvent; // eRPC thread #endif /********************************************************************* * PROFILE CALLBACKS */ // GAP Bond Manager Callbacks static gapBondCBs_t bleApp_bondMgrCBs = { bleApp_passcodeCB, // Passcode callback bleApp_pairStateCb // Pairing/Bonding state Callback }; #ifdef ADD_SIMPLE_PERIPHERAL // Simple GATT Profile Callbacks static simpleProfileCBs_t bleApp_simpleProfileCBs = { bleApp_charValueChangeCB // Simple GATT Characteristic value change callback }; #endif /********************************************************************* * Mesh Callbacks Global Variables */ #ifdef USE_APP_MENU BT_MESH_HB_CB_DEFINE(meshApp_hb_cb) = { .recv = meshApp_hbRecv, .sub_end = meshApp_hb_subEnd, }; #ifdef CONFIG_BT_MESH_FRIEND BT_MESH_FRIEND_CB_DEFINE(meshApp_friend_cb) = { .established = meshApp_friend_friendshipEstablished, .terminated = meshApp_friend_friendshipTerminated, }; #endif /* CONFIG_BT_MESH_FRIEND */ #ifdef CONFIG_BT_MESH_LOW_POWER BT_MESH_LPN_CB_DEFINE(meshApp_lpn_cb) = { .established = meshApp_lpn_friendshipEstablished, .terminated = meshApp_lpn_friendshipTerminated, .polled = meshApp_lpnPolled, }; #endif /* CONFIG_BT_MESH_LOW_POWER */ #endif /* USE_APP_MENU */ /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn bleApp_spin * * @brief Spin forever * * @param none */ static void bleApp_spin(void) { volatile uint8_t x = 0; while(1) { x++; } } #ifdef MESH_ERPC /********************************************************************* * @fn mesh_erpc_register * * @brief Register to ble stack from the eRPC context. * * @return none */ void mesh_erpc_register(void) { bleStack_errno_t err; // When eRPC is enabled, need to register to the ble stack from the eRPC context err = bleStack_register(&erpcThreadSelfEntity, 0); BLEAPP_ASSERT(BLE_STACK_ERRNO_SUCCESS == err); } #endif #ifdef ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn SimplePeripheral_initProfiles * * @brief Init simple peripheral profiles */ int SimplePeripheral_initProfiles(void) { DevInfo_AddService(); // Device Information Service SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile #if defined(OAD_SUPPORT_ONCHIP) // OAD profile for reset action OadApp_addService(); #endif // Setup the SimpleProfile Characteristic Values // For more information, see the GATT and GATTServApp sections in the User's Guide: // software-dl.ti.com/.../ { uint8_t charValue1 = 1; uint8_t charValue2 = 2; uint8_t charValue3 = 3; uint8_t charValue4 = 4; uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 }; SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t), &charValue1); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t), &charValue2); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t), &charValue3); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t), &charValue4); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5); } // Register callback with SimpleGATTprofile SimpleProfile_RegisterAppCBs(&bleApp_simpleProfileCBs); return 0; } #endif // ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn bleApp_stackInit * * @brief Called during initialization and contains application * specific initialization (ie. hardware initialization/setup, * table initialization, power up notification, etc), and * profile initialization/setup. */ int bleApp_stackInit(void) { uint8_t profileRole; // ****************************************************************** // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO bleStack_register // ****************************************************************** // Register the stack messages callback - see ble_stack_api.c - #ifdef ICALL_NO_APP_EVENTS bleStack_register(&appSelfEntity, bleApp_processStackMsgCB); meshAppSelfEntity = appSelfEntity; // used by bt.c // Create the application appSyncEvent appSyncEvent = Event_create(NULL, NULL); // Create an RTOS queue for message from profile to be sent to app. appMsgQueueHandle = Util_constructQueue(&appMsgQueue); // Create one-shot clock for internal periodic events. Util_constructClock(&clkPeriodic, bleApp_clockHandler, BLEAPP_PERIODIC_EVT_PERIOD, 0, false, (UArg)&argPeriodic); #if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) profileRole = GAP_PROFILE_PERIPHERAL | GAP_PROFILE_OBSERVER; BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- role PERIPHERAL+OBSERVER", profileRole); #else profileRole = GAP_PROFILE_BROADCASTER | GAP_PROFILE_OBSERVER; BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- role BROADCASTER+OBSERVER", profileRole); #endif // CONFIG_BT_MESH_PROXY || ADD_SIMPLE_PERIPHERAL #ifdef USE_RCOSC // Set device's Sleep Clock Accuracy #if ( HOST_CONFIG & ( CENTRAL_CFG | PERIPHERAL_CFG ) ) HCI_EXT_SetSCACmd(500); #endif // (CENTRAL_CFG | PERIPHERAL_CFG) RCOSC_enableCalibration(); #endif // USE_RCOSC #if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) // init GAP bleStack_initGap(profileRole, appSelfEntity, DEFAULT_PARAM_UPDATE_REQ_DECISION); // init GapBond bleStack_initGapBond(0, &bleApp_bondMgrCBs); // init GATT bleStack_initGatt(profileRole, appSelfEntity, attDeviceName); #else // init GAP bleStack_initGap(profileRole, appSelfEntity, 0); // init GapBond bleStack_initGapBond(0, &bleApp_bondMgrCBs); #endif #if defined ( GAP_BOND_MGR ) // Setup the GAP Bond Manager. For more information see the GAP Bond Manager // section in the User's Guide // ToDo - remove implementation from SysConfig // ToDo - set one call _all instaead of many calls to GAPBondMgr_SetParameter setBondManagerParameters(); #endif #ifdef ADD_SIMPLE_PERIPHERAL SimplePeripheral_initProfiles(); #endif #ifdef ADD_SIMPLE_PERIPHERAL // Initialize Connection List SimplePeripheral_clearConnListEntry(LINKDB_CONNHANDLE_ALL); // Initialize array to store connection handle and RSSI values SimplePeripheral_initPHYRSSIArray(); #endif BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- call GAP_DeviceInit", profileRole); //Initialize GAP layer for Peripheral and Central role and register to receive GAP events GAP_DeviceInit(profileRole, appSelfEntity, addrMode, &pRandomAddress); #ifdef PTM_MODE PTM_init(appSelfEntity); #endif #ifdef OAD_SUPPORT #ifdef OAD_DEBUG tbm_setItemStatus(&spMenuMain, SP_ITEM_SELECT_OAD_DBG, SP_ITEM_SELECT_CONN); #endif OadApp_init(); #endif // Preempting Advertise over Scan BLEAPP_ASSERT(HCI_EXT_SetQOSDefaultParameters(LL_QOS_MEDIUM_PRIORITY, LL_QOS_TYPE_PRIORITY, LL_QOS_ADV_TASK_TYPE) == HCI_SUCCESS); return 0; } /********************************************************************* * @fn bleApp_init * * @brief Called during initialization and contains application * specific initialization (ie. hardware initialization/setup, * table initialization, power up notification, etc), and * profile initialization/setup. */ static void bleApp_init(void) { BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- init ", BLEAPP_TASK_PRIORITY); /* * Init the menu with input keys and display */ // Init key debouncer Board_initKeys(bleApp_keyChangeHandler); #ifdef USE_APP_MENU // preprocessor definitions dispHandle = Display_open(Display_Type_ANY, NULL); // Create the menu // SimpleMeshMenu_init(dispHandle); #endif /* * Init the ble stack */ bleApp_stackInit(); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { // Initialize settings submodule int err = settings_subsys_init(); BLEAPP_ASSERT(err == SUCCESS); Display_printf(dispHandle, SMN_ROW_MENU_ST, 0, "NVS: settings_subsys_init() ret status: %d", err); } /* * Init the mesh stack */ #if defined (USE_APP_MENU) || defined (MESH_ERPC) // TBMenu will call MeshApp_init // eRpc will call bt_mesh_init + bt_mesh_provision #else // bt_ready now, zephyr mesh stack can be initialized MeshApp_init(mesh_own_addr, UNPROVISIONED_BEACON); #endif } /********************************************************************* * @fn simple_mesh_and_peripheral_createTask * * @brief Task creation function for simple_mesh_and_peripheral. */ void simple_mesh_and_peripheral_createTask(void) { Task_Params taskParams; // Configure task Task_Params_init(&taskParams); taskParams.stack = appTaskStack; taskParams.stackSize = BLEAPP_TASK_STACK_SIZE; taskParams.priority = BLEAPP_TASK_PRIORITY; Task_construct(&appTask, bleApp_taskFxn, &taskParams, NULL); } /********************************************************************* * @fn bleApp_createTasks * * @brief Task creation function for this ble application. */ void bleApp_createTasks(void) { // Init and create ble stack tasks bleStack_createTasks(); // init zephyr mesh worker task k_sys_work_q_init(NULL); #ifdef MESH_ERPC // create eRpc task eRpcMesh_createTask(); #endif // Create local app task simple_mesh_and_peripheral_createTask(); } /********************************************************************* * @fn bleApp_taskFxn * * @brief Application task entry point for the Simple Mesh. * * @param a0, a1 - not used. */ static void bleApp_taskFxn(UArg a0, UArg a1) { // Initialize application bleApp_init(); // Application main loop for (;;) { uint32_t events; appEvt_t *pMsg; // Waits for an event to be posted events = Event_pend(appSyncEvent, Event_Id_NONE, APP_QUEUE_EVT, EVENT_PEND_FOREVER); if (events) { // Check if there are any messages in the queue while (!Queue_empty(appMsgQueueHandle)) { pMsg = (appEvt_t *)Util_dequeueMsg(appMsgQueueHandle); if (pMsg) { if (BLEAPP_EVT_STACK_CALLBACK == pMsg->event) { // Process stack messages - changed from events to callback if (bleApp_processStackMsg((bleStack_msgHdt_t*)pMsg->pData)) { bleStack_freeMsg((bleStack_msgHdt_t*)pMsg->pData); } } #ifdef OAD_SUPPORT else if (OADAPP_EVT_CALLBACK == pMsg->event) { OadApp_processEvents((uint32_t)(*(uint8_t *)(pMsg->pData))); bleStack_free(pMsg->pData); } #endif else { // Process application messages (callbacks after switch context) bleApp_processAppMsg(pMsg); } // Free the space from the message. bleStack_free(pMsg); } } } } } /********************************************************************* * @fn bleApp_processStackMsg * * @brief Process an incoming stack message. * * @param pMsg - message to process * * @return TRUE if safe to deallocate incoming message, FALSE otherwise. */ static uint8_t bleApp_processStackMsg(bleStack_msgHdt_t *pMsg) { // Always dealloc pMsg unless set otherwise uint8_t safeToDealloc = TRUE; BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : Stack msg status=%d, event=0x%x\n", pMsg->status, pMsg->event); switch (pMsg->event) { case GAP_MSG_EVENT: bleApp_processGapMessage((gapEventHdr_t*) pMsg); break; case GATT_MSG_EVENT: // Process GATT message safeToDealloc = bleApp_processGATTMsg((gattMsgEvent_t *)pMsg); break; case HCI_GAP_EVENT_EVENT: { // Process HCI message switch (pMsg->status) { case HCI_COMMAND_COMPLETE_EVENT_CODE: // Process HCI Command Complete Events here { #ifdef ADD_SIMPLE_PERIPHERAL bleApp_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg); #endif break; } case HCI_BLE_HARDWARE_ERROR_EVENT_CODE: AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0); break; #ifdef ADD_SIMPLE_PERIPHERAL // HCI Commands Events case HCI_COMMAND_STATUS_EVENT_CODE: { hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg; switch ( pMyMsg->cmdOpcode ) { case HCI_LE_SET_PHY: { if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE) { Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "PHY Change failure, peer does not support this"); } else { Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "PHY Update Status Event: 0x%x", pMyMsg->cmdStatus); } SimplePeripheral_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg); break; } default: break; } break; } // LE Events case HCI_LE_EVENT_CODE: { hciEvt_BLEPhyUpdateComplete_t *pPUC = (hciEvt_BLEPhyUpdateComplete_t*) pMsg; // A Phy Update Has Completed or Failed if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT) { if (pPUC->status != SUCCESS) { Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "PHY Change failure"); } else { // Only symmetrical PHY is supported. // rxPhy should be equal to txPhy. Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "PHY Updated to %s", (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1M" : (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2M" : (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value"); } SimplePeripheral_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT, (uint8_t *)pMsg); } break; } #endif // ADD_SIMPLE_PERIPHERAL default: break; } break; } #ifdef OAD_SUPPORT case L2CAP_SIGNAL_EVENT: // Process L2CAP signal safeToDealloc = OadApp_processL2CAPMsg((l2capSignalEvent_t *)pMsg); break; #endif default: // Do nothing break; } #ifdef PTM_MODE // Check for NPI Messages PTM_handle_hci_event(pMsg); #endif return (safeToDealloc); } /********************************************************************* * @fn bleApp_processGATTMsg * * @brief Process GATT messages and events. * * @return TRUE if safe to deallocate incoming message, FALSE otherwise. */ static uint8_t bleApp_processGATTMsg(gattMsgEvent_t *pMsg) { #ifdef ADD_SIMPLE_PERIPHERAL if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT) { // ATT request-response or indication-confirmation flow control is // violated. All subsequent ATT requests or indications will be dropped. // The app is informed in case it wants to drop the connection. // Display the opcode of the message that caused the violation. Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode); } else if (pMsg->method == ATT_MTU_UPDATED_EVENT) { // MTU size updated #ifdef OAD_SUPPORT OAD_setBlockSize(pMsg->msg.mtuEvt.MTU); #endif Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU); } #endif // ADD_SIMPLE_PERIPHERAL #ifdef CONFIG_BT_MESH_PROXY if (pMsg->method == ATT_MTU_UPDATED_EVENT) { mesh_portingLayer_updateLinkMTU(pMsg->msg.mtuEvt.MTU); } #endif // Free message payload. Needed only for ATT Protocol messages GATT_bm_free(&pMsg->msg, pMsg->method); // It's safe to free the incoming message return (TRUE); } /********************************************************************* * @fn bleApp_processAppMsg * * @brief Process an incoming callback from a profile. * * @param pMsg - message to process * * @return None. */ static void bleApp_processAppMsg(appEvt_t *pMsg) { bool dealloc = TRUE; if (pMsg->event <= BLEAPP_EVT_EVENT_MAX) { BLE_LOG_INT_STR(0, BLE_LOG_MODULE_APP, "APP : App msg status=%d, event=%s\n", 0, appEventStrings[pMsg->event]); } else { BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : App msg status=%d, event=0x%x\n", 0, pMsg->event); } switch (pMsg->event) { #ifdef ADD_SIMPLE_PERIPHERAL case BLEAPP_EVT_CHAR_CHANGE: bleApp_processCharValueChangeEvt(*(uint8_t*)(pMsg->pData)); break; #endif #ifdef USE_APP_MENU case BLEAPP_EVT_KEY_CHANGE: bleApp_handleKeys(*(uint8_t *)(pMsg->pData)); break; #endif #ifdef ADD_SIMPLE_PERIPHERAL case BLEAPP_EVT_ADV: advCb_count++; bleApp_processAdvEvent((appGapAdvEventData_t*)(pMsg->pData)); break; #endif case MESHAPP_EVT_ADV: advCb_count++; meshApp_processAdvEvent((appGapAdvEventData_t*)(pMsg->pData)); break; case BLEAPP_EVT_PERIODIC: bleApp_performPeriodicTask(); break; #ifdef ADD_SIMPLE_PERIPHERAL case BLEAPP_EVT_PAIRING_STATE: bleApp_processPairState((appPairStateData_t*)(pMsg->pData)); break; case BLEAPP_EVT_PASSCODE_NEEDED: bleApp_processPasscode((appPasscodeData_t*)(pMsg->pData)); break; case BLEAPP_EVT_READ_RPA: SimplePeripheral_updateRPA(); break; case BLEAPP_EVT_SEND_PARAM_UPDATE: { // Extract connection handle from data uint16_t connHandle = *(uint16_t *)(((appClockEventData_t *)pMsg->pData)->data); bleApp_processParamUpdate(connHandle); // This data is not dynamically allocated dealloc = FALSE; break; } case BLEAPP_EVT_CONN: bleApp_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData)); break; #if defined(OAD_SUPPORT_ONCHIP) case OADAPP_EVT_RESET: OadApp_processOadResetEvt((oadResetWrite_t *)(pMsg->pData)); break; #endif #endif // ADD_SIMPLE_PERIPHERAL case BLEAPP_EVT_ADV_REPORT: { scanCbData_t *pData = (scanCbData_t *)pMsg->pData; GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pData->pMsg); mesh_portingLayer_scanCB(pData->evt, pData->pMsg, pData->arg); #define BT_DATA_MESH_PROV 0x29 /* Mesh Provisioning PDU */ #define BT_DATA_MESH_MESSAGE 0x2a /* Mesh Networking PDU */ #define BT_DATA_MESH_BEACON 0x2b /* Mesh Beacon */ scanCb_count++; if (pAdvRpt->pData[1] == BT_DATA_MESH_BEACON) scanCb_beaconCount++; else if (pAdvRpt->pData[1] == BT_DATA_MESH_MESSAGE) scanCb_msgCount++; else if (pAdvRpt->pData[1] == BT_DATA_MESH_PROV) scanCb_provCount++; // Free scan payload data if (pAdvRpt->pData != NULL) { bleStack_free(pAdvRpt->pData); } if (pAdvRpt != NULL) { bleStack_free(pAdvRpt); } break; } case BLEAPP_EVT_SCAN_ENABLED: case BLEAPP_EVT_SCAN_DISABLED: { scanCbData_t *pData = (scanCbData_t *)pMsg->pData; mesh_portingLayer_scanCB(pData->evt, pData->pMsg, pData->arg); break; } case BLEAPP_EVT_INSUFFICIENT_MEM: { // We are running out of memory. #ifdef USE_APP_MENU // Display_printf(dispHandle, SMN_ROW_ANY_CONN, 0, "Insufficient Memory"); #endif BLEAPP_ASSERT(FAILURE); break; } #ifdef CONFIG_BT_MESH_PROXY case MESHAPP_EVT_GATT_WRT: { writeCbParams_t *writeParams = (writeCbParams_t *)(pMsg->pData); // call real writeCB mesh_portingLayer_proxyProvAttWriteCB(writeParams); break; } #endif default: // Do nothing. break; } // Free message data if it exists and we are to dealloc if ((dealloc == TRUE) && (pMsg->pData != NULL)) { bleStack_free(pMsg->pData); } } #ifdef ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn SimplePeripheral_initAdvSet * * @brief Initialize and starts advertise set (legacy or extended) * * @param advCallback Function pointer to a callback for this advertising set * @param advHandle Output parameter to return the created advertising handle * @param advParams pointer to structure of adversing parameters * @param advData pointer to array containing the advertise data * @param advDataLen length (in bytes) of @ref advData * @param scanRespData pointer to array containing the scan response data * @param scanRespDataLen length (in bytes) of @ref scanRespDataLen * * @return @ref SUCCESS upon successful initialization, * else, relevant error code upon failure */ static bStatus_t SimplePeripheral_initAdvSet(pfnGapCB_t advCallback, uint8_t * const advHandle, GapAdv_params_t * const advParams, uint8_t advData[], const int advDataLen, uint8_t scanRespData[], const int scanRespDataLen) { bStatus_t status; BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : ---- call GapAdv_create set=%d,%d\n", 0, 0); // Create Advertisement set and assign handle status = GapAdv_create(advCallback, advParams, advHandle); if (status != SUCCESS) { return status; } // Load advertising data for set that is statically allocated by the app status = GapAdv_loadByHandle(*advHandle, GAP_ADV_DATA_TYPE_ADV, advDataLen, advData); if (status != SUCCESS) { return status; } // Load scan response data for set that is statically allocated by the app if (scanRespData != NULL) { status = GapAdv_loadByHandle(*advHandle, GAP_ADV_DATA_TYPE_SCAN_RSP, scanRespDataLen, scanRespData); if (status != SUCCESS) { return status; } } // Set event mask for set status = GapAdv_setEventMask(*advHandle, GAP_ADV_EVT_MASK_START_AFTER_ENABLE | GAP_ADV_EVT_MASK_END_AFTER_DISABLE | GAP_ADV_EVT_MASK_SET_TERMINATED); if (status != SUCCESS) { return status; } // Enable advertising for set status = GapAdv_enable(*advHandle, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0); return status; } /********************************************************************* * @fn SimplePeripheral_startAdvertising * * @brief start advertising - legacy and long range */ int SimplePeripheral_startAdvertising(uint8_t *devAddr) { bStatus_t status; Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Initialized"); // Setup and start Advertising // For more information, see the GAP section in the User's Guide: // software-dl.ti.com/.../ // Initialize advertisement handlers // In case of extended, initialize advertise set with advertising data, // else (Legacy), initialize advertise set with scan response data and advertising data // Note: In this example, the default adv set is extended. When changing the set to Legacy, // please un-comment the "else" section. if ( (advParams1.eventProps & GAP_ADV_PROP_LEGACY) == 0) { status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle1, &advParams1, advData1, sizeof(advData1) ,NULL, 0); BLEAPP_ASSERT(status == SUCCESS); } // else // { // status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle1, &advParams1, // advData1, sizeof(advData1) , // scanResData1, sizeof(scanResData1)); // BLEAPP_ASSERT(status == SUCCESS); // } #ifdef SECOND_ADV_SET // In case of extended, initialize advertise set with advertising data, // else (Legacy), initialize advertise set with scan response data and advertising data // Note: In this example, the default adv set is extended. When changing the set to Legacy, // please un-comment the "else" section. if (advParams2.eventProps & GAP_ADV_PROP_LEGACY == 0) { status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle2, &advParams2, advData2, sizeof(advData2) ,NULL, 0); BLEAPP_ASSERT(status == SUCCESS); } // else // { // status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle2, &advParams2, // advData2, sizeof(advData2) , // scanResData2, sizeof(scanResData2)); // BLEAPP_ASSERT(status == SUCCESS); // } #endif /* SECOND_ADV_SET */ // Display device address Display_printf(dispHandle, SP_ROW_IDA, 0, "%s Addr: %s", (addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID", Util_convertBdAddr2Str(devAddr)); if (addrMode > ADDRMODE_RANDOM) { SimplePeripheral_updateRPA(); // Create one-shot clock for RPA check event. Util_constructClock(&clkRpaRead, bleApp_clockHandler, READ_RPA_PERIOD, 0, true, (UArg) &argRpaRead); } tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, TBM_ITEM_NONE); return 0; } /********************************************************************* * @fn SimplePeripheral_connectIndication * * @brief conection establish indication */ int SimplePeripheral_connectIndication(uint16_t connectionHandle, uint8 pkt_status) { // Display the amount of current connections uint8_t numActive = linkDB_NumActive(); #ifdef USE_APP_MENU Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Num Conns: %d", (uint16_t)numActive); #endif if (pkt_status == SUCCESS) { // Add connection to list and start RSSI SimplePeripheral_addConn(connectionHandle); // Enable connection selection option tbm_setItemStatus(&spMenuMain, SP_ITEM_SELECT_CONN,SP_ITEM_AUTOCONNECT); // Start Periodic Clock. Util_startClock(&clkPeriodic); } if ((numActive < MAX_NUM_BLE_CONNS) && (autoConnect == AUTOCONNECT_DISABLE)) { // Start advertising since there is room for more connections GapAdv_enable(advHandle1, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0); #ifdef SECOND_ADV_SET GapAdv_enable(advHandle2, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0); #endif /* SECOND_ADV_SET */ } else { GapAdv_disable(advHandle1); #ifdef SECOND_ADV_SET GapAdv_disable(advHandle2); #endif /* SECOND_ADV_SET */ } return 0; } /********************************************************************* * @fn SimplePeripheral_disableAdvertising * * @brief disable advertising - legacy and long range */ int SimplePeripheral_disconnectIndication(uint16_t connectionHandle) { // Display the amount of current connections uint8_t numActive = linkDB_NumActive(); #ifdef USE_APP_MENU Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Device Disconnected!"); Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Num Conns: %d", (uint16_t)numActive); #endif // Remove the connection from the list and disable RSSI if needed SimplePeripheral_removeConn(connectionHandle); // If no active connections if (numActive == 0) { // Stop periodic clock Util_stopClock(&clkPeriodic); // Disable Connection Selection option tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, SP_ITEM_SELECT_CONN); } BLE_LOG_INT_STR(0, BLE_LOG_MODULE_APP, "APP : GAP msg: status=%d, opcode=%s\n", 0, "GAP_LINK_TERMINATED_EVENT"); // Start advertising since there is room for more connections GapAdv_enable(advHandle1, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0); #ifdef SECOND_ADV_SET GapAdv_enable(advHandle2, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0); #endif /* SECOND_ADV_SET */ // Clear remaining lines Display_clearLine(dispHandle, SP_ROW_CONNECTION); #ifdef OAD_SUPPORT // Cancel the OAD if one is going on // A disconnect forces the peer to re-identify OadApp_cancel(); #endif return 0; } #endif // ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn bleApp_processGapMessage * * @brief Process an incoming GAP event. * * @param pMsg - message to process */ static void bleApp_processGapMessage(gapEventHdr_t *pMsg) { switch (pMsg->opcode) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg; BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- got GAP_DEVICE_INIT_DONE_EVENT", 0); if(pPkt->hdr.status == SUCCESS) { // Store the system ID uint8_t systemId[DEVINFO_SYSTEM_ID_LEN]; // use 6 bytes of device address for 8 bytes of system ID value systemId[0] = pPkt->devAddr[0]; systemId[1] = pPkt->devAddr[1]; systemId[2] = pPkt->devAddr[2]; // set middle bytes to zero systemId[4] = 0x00; systemId[3] = 0x00; // shift three bytes up systemId[7] = pPkt->devAddr[5]; systemId[6] = pPkt->devAddr[4]; systemId[5] = pPkt->devAddr[3]; // Set Device Info Service Parameter DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); // Register callback to process Scanner events GapScan_registerCb(MeshApp_scanCB, NULL); #ifdef CONFIG_BT_MESH_PROXY // Set the device's name in the mesh porting layer mesh_portingLayer_setDeviceName(meshScanData); #endif #ifdef ADD_SIMPLE_PERIPHERAL SimplePeripheral_startAdvertising(pPkt->devAddr); #endif } break; } case GAP_LINK_ESTABLISHED_EVENT: { #if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- got GAP_LINK_ESTABLISHED_EVENT", 0); #endif #ifdef CONFIG_BT_MESH_PROXY // Call zephyr cb mesh_portingLayer_newConnectionCB(pPkt); #endif #ifdef ADD_SIMPLE_PERIPHERAL SimplePeripheral_connectIndication(pPkt->connectionHandle, pPkt->hdr.status); #endif break; } case GAP_LINK_TERMINATED_EVENT: { #if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; #endif #ifdef CONFIG_BT_MESH_PROXY // Call zephyr cb mesh_portingLayer_disconnectCB(pPkt); #endif #ifdef ADD_SIMPLE_PERIPHERAL SimplePeripheral_disconnectIndication(pPkt->connectionHandle); #endif break; } #if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) case GAP_UPDATE_LINK_PARAM_REQ_EVENT: { gapUpdateLinkParamReqReply_t rsp; gapUpdateLinkParamReqEvent_t *pReq = (gapUpdateLinkParamReqEvent_t *)pMsg; rsp.connectionHandle = pReq->req.connectionHandle; rsp.signalIdentifier = pReq->req.signalIdentifier; // Only accept connection intervals with slave latency of 0 // This is just an example of how the application can send a response if(pReq->req.connLatency == 0) { rsp.intervalMin = pReq->req.intervalMin; rsp.intervalMax = pReq->req.intervalMax; rsp.connLatency = pReq->req.connLatency; rsp.connTimeout = pReq->req.connTimeout; rsp.accepted = TRUE; } else { rsp.accepted = FALSE; } // Send Reply VOID GAP_UpdateLinkParamReqReply(&rsp); break; } case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Get the address from the connection handle linkDBInfo_t linkInfo; linkDB_GetInfo(pPkt->connectionHandle, &linkInfo); #ifdef CONFIG_BT_MESH_PROXY mesh_portingLayer_updateLinkMTU(linkInfo.MTU); #endif #ifdef ADD_SIMPLE_PERIPHERAL #ifdef USE_APP_MENU if(pPkt->status == SUCCESS) { // Display the address of the connection update Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Updated: %s", Util_convertBdAddr2Str(linkInfo.addr)); } else { // Display the address of the connection update failure Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Update Failed 0x%x: %s", pPkt->opcode, Util_convertBdAddr2Str(linkInfo.addr)); } #endif // Check if there are any queued parameter updates spConnHandleEntry_t *connHandleEntry = (spConnHandleEntry_t *)List_get(¶mUpdateList); if (connHandleEntry != NULL) { // Attempt to send queued update now bleApp_processParamUpdate(connHandleEntry->connHandle); // Free list element bleStack_free(connHandleEntry); } #endif // ADD_SIMPLE_PERIPHERAL break; } #if defined ( NOTIFY_PARAM_UPDATE_RJCT ) case GAP_LINK_PARAM_UPDATE_REJECT_EVENT: { linkDBInfo_t linkInfo; gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Get the address from the connection handle linkDB_GetInfo(pPkt->connectionHandle, &linkInfo); // Display the address of the connection update failure Display_printf(dispHandle, SP_ROW_CONNECTION, 0, "Peer Device's Update Request Rejected 0x%h: %s", pPkt->opcode, Util_convertBdAddr2Str(linkInfo.addr)); break; } #endif #endif /* defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) */ default: #ifdef ADD_SIMPLE_PERIPHERAL Display_clearLines(dispHandle, SP_ROW_STATUS_1, SP_ROW_STATUS_2); #endif // ADD_SIMPLE_PERIPHERAL break; } } /********************************************************************* * @fn bleApp_processStackMsgCB * * @brief Callback for application from ble stack * * @param pMessage - message from ble stack * * @return None. */ uint8_t bleApp_processStackMsgCB(uint8_t event, uint8_t *pMessage) { // ignore the event // Enqueue the msg in order to be excuted in the application context bleApp_enqueueMsg(BLEAPP_EVT_STACK_CALLBACK, pMessage); // not safe to dealloc, the application layer will free the msg return (false); } #ifdef OAD_SUPPORT /********************************************************************* * @fn bleApp_processOadEventsInAppContext * * @brief Callback from OAD to handle OAD events * * @param event - event from OAD * * @return None. */ uint8_t bleApp_processOadEventsInAppContext(uint8_t *pEventData) { // Enqueue the msg in order to be excuted in the application context bleApp_enqueueMsg(OADAPP_EVT_CALLBACK, pEventData); // not safe to dealloc, the application layer will free the msg return (false); } #if defined(OAD_SUPPORT_ONCHIP) /********************************************************************* * @fn bleApp_processOadResetInAppContext * * @brief Callback from OAD to handle OAD reset * * @param event - event from OAD * * @return None. */ uint8_t bleApp_processOadResetInAppContext(uint8_t *pEventData) { // Enqueue the msg in order to be excuted in the application context bleApp_enqueueMsg(OADAPP_EVT_RESET, pEventData); // not safe to dealloc, the application layer will free the msg return (false); } #endif // OAD_SUPPORT_ONCHIP #endif // OAD_SUPPORT #ifdef ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn bleApp_charValueChangeCB * * @brief Callback from Simple Profile indicating a characteristic * value change. * * @param paramId - parameter Id of the value that was changed. * * @return None. */ static void bleApp_charValueChangeCB(uint8_t paramId) { uint8_t *pValue = bleStack_malloc(sizeof(uint8_t)); if (pValue) { *pValue = paramId; if(bleApp_enqueueMsg(BLEAPP_EVT_CHAR_CHANGE, pValue) != SUCCESS) { bleStack_free(pValue); } } } #endif // ADD_SIMPLE_PERIPHERAL #ifdef ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn bleApp_processCharValueChangeEvt * * @brief Process a pending Simple Profile characteristic value change * event. * * @param paramID - parameter ID of the value that was changed. */ static void bleApp_processCharValueChangeEvt(uint8_t paramId) { uint8_t newValue; switch(paramId) { case SIMPLEPROFILE_CHAR1: SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue); Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Char 1: %d", (uint16_t)newValue); break; case SIMPLEPROFILE_CHAR3: SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue); Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Char 3: %d", (uint16_t)newValue); break; default: // should not reach here! break; } } #endif // ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn bleApp_performPeriodicTask * * @brief Perform a periodic application task. This function gets called * every two seconds (BLEAPP_PERIODIC_EVT_PERIOD). * * @param None. * * @return None. */ static void bleApp_performPeriodicTask(void) { #if defined(USE_APP_MENU) && defined(DEBUG_MESH_APP) Display_printf(dispHandle, SMN_ROW_CBCK_ST, 0, "CBCK: advCb count=%04d, scanCb=%04d, beacon=%04x, msg=%04x, prov=%04x", advCb_count, scanCb_count, scanCb_beaconCount, scanCb_msgCount, scanCb_provCount); #endif #ifdef ADD_SIMPLE_PERIPHERAL uint8_t valueToCopy; // Call to retrieve the value of the third characteristic in the profile if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS) { // Call to set that value of the fourth characteristic in the profile. // Note that if notifications of the fourth characteristic have been // enabled by a GATT client device, then a notification will be sent // every time this function is called. SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t), &valueToCopy); } #endif // ADD_SIMPLE_PERIPHERAL } #ifdef ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn SimplePeripheral_updateRPA * * @brief Read the current RPA from the stack and update display * if the RPA has changed. * * @param None. * * @return None. */ static void SimplePeripheral_updateRPA(void) { uint8_t* pRpaNew; // Read the current RPA. pRpaNew = GAP_GetDevAddress(FALSE); if (memcmp(pRpaNew, rpa, B_ADDR_LEN)) { // If the RPA has changed, update the display Display_printf(dispHandle, SP_ROW_RPA, 0, "RP Addr: %s", Util_convertBdAddr2Str(pRpaNew)); memcpy(rpa, pRpaNew, B_ADDR_LEN); } } #endif // ADD_SIMPLE_PERIPHERAL /********************************************************************* * @fn SimpleMeshNode_advCB * * @brief GapAdv module callback, called from MESH stack * * @param pMsg - message to process */ void SimpleMeshNode_advCB(uint32_t event, void *pBuf, uintptr_t arg) { appGapAdvEventData_t *pData = bleStack_malloc(sizeof(appGapAdvEventData_t)); if (pData) { pData->event = event; pData->pBuf = pBuf; if(bleApp_enqueueMsg(MESHAPP_EVT_ADV, pData) != SUCCESS) { bleStack_free(pData); } } }
/* * start_provisioning.c * * Created on: 19 janv. 2023 * Author: alexa */ #include <stdio.h> #include <stdint.h> #include <stddef.h> #include <string.h> #include <math.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Clock.h> #include <ti/sysbios/knl/Event.h> #include <ti/sysbios/knl/Queue.h> #include <ti/sysbios/knl/Semaphore.h> #include <ti/sysbios/BIOS.h> #include <bluetooth/bluetooth.h> #include <bluetooth/mesh.h> #include <bt_le_porting_layer.h> #include <start_provisioning.h> #include <ti/drivers/GPIO.h> #include "ti_drivers_config.h" #include <simple_mesh_node.h> #include "ti_ble_mesh_config.h" #include <simple_mesh_node_menu.h> #include <net/buf.h> #include <include/bluetooth/mesh/access.h> #include "static_prov.h" #define START_PROV_TASK_PRIORITY 3 #ifndef START_PROV_STACK_SIZE #define START_PROV_STACK_SIZE 2248 #endif #define GROUP_ADDR 0xc000 extern void start_prov_init(void); uint8_t button_state = 0; uint8_t led_state = 0; uint16_t addr; uint16_t mesh_device_own_addr = DEVICE_OWN_ADDRESS; extern uint16_t mesh_btn_target_addr; //static const uint16_t app_idx; Task_Struct start_prov_Task; uint8_t start_prov_Stack[START_PROV_STACK_SIZE]; Semaphore_Struct semstart_prov_Task_Struct; Semaphore_Handle semstart_prov_Task_Handle; Semaphore_Struct semstart_led_Task_Struct; Semaphore_Handle semstart_led_Task_Handle; void provision_done_cbk() { GPIO_write(CONFIG_GPIO_LED_0,1); } void btn1fxn_cbk(uint_least8_t index) { Semaphore_post(semstart_prov_Task_Handle); } void btn2fxn_cbk(uint_least8_t index) { Semaphore_post(semstart_led_Task_Handle); } void turnLed(uint8_t on_off) { if (on_off) { GPIO_write(CONFIG_GPIO_LED_1,1); } else { GPIO_write(CONFIG_GPIO_LED_1,0); } } void Mesh_doButton(uint8_t index) { if (index == 0) // turn LED on { MeshApp_button_pressed(1); } else if (index == 1) // turn LED off { MeshApp_button_pressed(0); } } void button_pressed_cb(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { // check own address if (ctx->addr == mesh_device_own_addr ) { return; } uint8_t led_state = net_buf_simple_pull_u8(buf); //SimpleMeshMenu_turnLed(led_state); turnLed(led_state); } void start_prov_init(void) { GPIO_init(); GPIO_setConfig(CONFIG_GPIO_BTN1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); GPIO_setCallback(CONFIG_GPIO_BTN1,btn1fxn_cbk ); GPIO_enableInt(CONFIG_GPIO_BTN1); GPIO_init(); GPIO_setConfig(CONFIG_GPIO_BTN2, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); GPIO_setCallback(CONFIG_GPIO_BTN2,btn2fxn_cbk ); GPIO_enableInt(CONFIG_GPIO_BTN2); GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); } static void start_prov_taskFxn(UArg a0, UArg a1) { start_prov_init(); bleApp_stackInit(); /* MeshApp_init(DEVICE_OWN_ADDRESS, UNPROVISIONED_BEACON); MeshApp_static_provisioning(DEVICE_OWN_ADDRESS, BT_MESH_KEY_UNUSED);*/ for (;;) { Semaphore_pend(semstart_prov_Task_Handle, BIOS_WAIT_FOREVER); MeshApp_init(DEVICE_OWN_ADDRESS, UNPROVISIONED_BEACON); Semaphore_pend(semstart_led_Task_Handle, BIOS_WAIT_FOREVER); mesh_btn_target_addr = GROUP_ADDR; button_state = 0; Mesh_doButton(button_state); } } void start_prov_CreateTask(void) { bleStack_createTasks(); k_sys_work_q_init(NULL); Semaphore_Params semParams; Task_Params taskParams; Task_Params_init(&taskParams); taskParams.stack = start_prov_Stack; taskParams.stackSize = START_PROV_STACK_SIZE; taskParams.priority = START_PROV_TASK_PRIORITY; Task_construct(&start_prov_Task, start_prov_taskFxn, &taskParams, NULL); Semaphore_Params_init(&semParams); Semaphore_construct(&semstart_prov_Task_Struct, 0, &semParams); semstart_prov_Task_Handle = Semaphore_handle( &semstart_prov_Task_Struct); Semaphore_construct(&semstart_led_Task_Struct, 0, &semParams); semstart_led_Task_Handle = Semaphore_handle( &semstart_led_Task_Struct); }