| /* USER CODE BEGIN Header */ |
| /** |
| ****************************************************************************** |
| * File Name : app_entry.c |
| * Description : Entry application source file for STM32WPAN Middleware. |
| ****************************************************************************** |
| * @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. |
| * |
| ****************************************************************************** |
| */ |
| /* USER CODE END Header */ |
| |
| /* Includes ------------------------------------------------------------------*/ |
| #include "app_entry.h" |
| #include "app_ble.h" |
| #include "app_common.h" |
| #include "app_conf.h" |
| #include "app_thread.h" |
| #include "cmsis_os.h" |
| #include "dbg_trace.h" |
| #include "hw_conf.h" |
| #include "main.h" |
| #include "shci.h" |
| #include "shci_tl.h" |
| #include "ssd1315.h" |
| #include "stm32_lcd.h" |
| #include "stm32_lpm.h" |
| #include "stm32wb5mm_dk_lcd.h" |
| #include "stm_logging.h" |
| |
| #include "AppTask.h" |
| /* Private includes -----------------------------------------------------------*/ |
| /* USER CODE BEGIN Includes */ |
| |
| /* USER CODE END Includes */ |
| |
| /* Private typedef -----------------------------------------------------------*/ |
| /* USER CODE BEGIN PTD */ |
| |
| /* USER CODE END PTD */ |
| |
| /* Private defines -----------------------------------------------------------*/ |
| /* POOL_SIZE = 2(TL_PacketHeader_t) + 258 (3(TL_EVT_HDR_SIZE) + 255(Payload size)) */ |
| #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4)) |
| /* USER CODE BEGIN PD */ |
| |
| /* USER CODE END PD */ |
| |
| /* Private macros ------------------------------------------------------------*/ |
| /* USER CODE BEGIN PM */ |
| |
| /* USER CODE END PM */ |
| |
| /* Private variables ---------------------------------------------------------*/ |
| |
| extern RTC_HandleTypeDef hrtc; /**< RTC handler declaration */ |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t EvtPool[POOL_SIZE]; |
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t SystemCmdBuffer; |
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t SystemSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; |
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; |
| uint8_t g_ot_notification_allowed = 0U; |
| /* Global variables ----------------------------------------------------------*/ |
| |
| /* Global function prototypes -----------------------------------------------*/ |
| #if (CFG_DEBUG_TRACE != 0) |
| size_t DbgTraceWrite(int handle, const unsigned char * buf, size_t bufSize); |
| #endif |
| |
| /* USER CODE BEGIN GFP */ |
| osSemaphoreId_t SemShciId; |
| osSemaphoreId_t SemShciUserEvtProcessId; |
| osThreadId_t OsShciUserEvtProcessId; |
| osThreadId_t OsPushButtonProcessId; |
| |
| const osThreadAttr_t ShciUserEvtProcess_attr = { .name = CFG_SHCI_USER_EVT_PROCESS_NAME, |
| .attr_bits = CFG_SHCI_USER_EVT_PROCESS_ATTR_BITS, |
| .cb_mem = CFG_SHCI_USER_EVT_PROCESS_CB_MEM, |
| .cb_size = CFG_SHCI_USER_EVT_PROCESS_CB_SIZE, |
| .stack_mem = CFG_SHCI_USER_EVT_PROCESS_STACK_MEM, |
| .stack_size = CFG_SHCI_USER_EVT_PROCESS_STACK_SIZE, |
| .priority = CFG_SHCI_USER_EVT_PROCESS_PRIORITY }; |
| |
| const osThreadAttr_t PushButtonProcess_attr = { .name = CFG_PUSH_BUTTON_EVT_PROCESS_NAME, |
| .attr_bits = CFG_PUSH_BUTTON_EVT_PROCESS_ATTR_BITS, |
| .cb_mem = CFG_PUSH_BUTTON_EVT_PROCESS_CB_MEM, |
| .cb_size = CFG_PUSH_BUTTON_EVT_PROCESS_CB_SIZE, |
| .stack_mem = CFG_PUSH_BUTTON_EVT_PROCESS_STACK_MEM, |
| .stack_size = CFG_PUSH_BUTTON_EVT_PROCESS_STACK_SIZE, |
| .priority = CFG_PUSH_BUTTON_EVT_PROCESS_PRIORITY }; |
| |
| /* USER CODE END GFP */ |
| |
| /* Private functions prototypes-----------------------------------------------*/ |
| static void SystemPower_Config(void); |
| static void Init_Debug(void); |
| static void APPE_SysStatusNot(SHCI_TL_CmdStatus_t status); |
| static void APPE_SysUserEvtRx(void * pPayload); |
| static void APPE_SysEvtReadyProcessing(void); |
| static void APPE_SysEvtError(SCHI_SystemErrCode_t ErrorCode); |
| static void appe_Tl_Init(void); |
| /* USER CODE BEGIN PFP */ |
| static void Led_Init(void); |
| static void Button_Init(void); |
| #if (CFG_HW_EXTPA_ENABLED == 1) |
| static void ExtPA_Init(void); |
| #endif |
| static void ShciUserEvtProcess(void * argument); |
| static void PushButtonEvtProcess(void * argument); |
| /* USER CODE END PFP */ |
| |
| static void displayConcurrentMode(void); |
| |
| // Callback function to handle pushbutton to apptask |
| PushButtonCallback PbCb = NULL; |
| |
| void APP_ENTRY_PBSetReceiveCallback(PushButtonCallback aCallback) |
| { |
| PbCb = aCallback; |
| } |
| |
| /* Functions Definition ------------------------------------------------------*/ |
| void APPE_Init(void) |
| { |
| /* Configure the system Power Mode */ |
| SystemPower_Config(); |
| |
| /* Initialize the TimerServer */ |
| HW_TS_Init(hw_ts_InitMode_Full, &hrtc); |
| |
| /* USER CODE BEGIN APPE_Init_1 */ |
| /* initialize debugger module if supported and debug trace if activated */ |
| Init_Debug(); |
| |
| /* Display Dynamic concurrent mode (BLE and Thread) */ |
| displayConcurrentMode(); |
| |
| /** |
| * The Standby mode should not be entered before the initialization is over |
| * The default state of the Low Power Manager is to allow the Standby Mode so an request is needed here |
| */ |
| UTIL_LPM_SetOffMode(1 << CFG_LPM_APP, UTIL_LPM_DISABLE); |
| |
| /** init freertos semaphore */ |
| SemShciId = osSemaphoreNew(1, 0, NULL); /*< Create the semaphore and make it busy at initialization */ |
| SemShciUserEvtProcessId = osSemaphoreNew(1, 0, NULL); /*< Create the semaphore and make it busy at initialization */ |
| OsShciUserEvtProcessId = osThreadNew(ShciUserEvtProcess, NULL, &ShciUserEvtProcess_attr); |
| OsPushButtonProcessId = osThreadNew(PushButtonEvtProcess, NULL, &PushButtonProcess_attr); |
| |
| Led_Init(); |
| Button_Init(); |
| |
| /* USER CODE END APPE_Init_1 */ |
| /* Initialize all transport layers and start CPU2 which will send back a ready event to CPU1 */ |
| appe_Tl_Init(); |
| |
| BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE); |
| /* Set LCD Foreground Layer */ |
| UTIL_LCD_SetFuncDriver(&LCD_Driver); /* SetFunc before setting device */ |
| UTIL_LCD_SetDevice(0); /* SetDevice after funcDriver is set */ |
| BSP_LCD_Clear(0, SSD1315_COLOR_BLACK); |
| BSP_LCD_DisplayOn(0); |
| BSP_LCD_Refresh(0); |
| UTIL_LCD_SetFont(&Font12); |
| /* Set the LCD Text Color */ |
| UTIL_LCD_SetTextColor(SSD1315_COLOR_WHITE); |
| UTIL_LCD_SetBackColor(SSD1315_COLOR_BLACK); |
| BSP_LCD_Clear(0, SSD1315_COLOR_BLACK); |
| BSP_LCD_Refresh(0); |
| UTIL_LCD_DisplayStringAt(0, 0, (uint8_t *) "Matter LightingApp", CENTER_MODE); |
| BSP_LCD_Refresh(0); |
| |
| /** |
| * From now, the application is waiting for the ready event ( VS_HCI_C2_Ready ) |
| * received on the system channel before starting the Stack |
| * This system event is received with APPE_SysUserEvtRx() |
| */ |
| /* USER CODE BEGIN APPE_Init_2 */ |
| #if (CFG_HW_EXTPA_ENABLED == 1) |
| ExtPA_Init(); |
| #endif |
| |
| /* USER CODE END APPE_Init_2 */ |
| return; |
| } |
| |
| static void displayConcurrentMode() |
| { |
| APP_DBG("Matter Over Thread Lighting-App starting..."); |
| } |
| |
| /************************************************************* |
| * |
| * LOCAL FUNCTIONS |
| * |
| *************************************************************/ |
| static void Init_Debug(void) |
| { |
| #if (CFG_DEBUGGER_SUPPORTED == 1) |
| /** |
| * Keep debugger enabled while in any low power mode |
| */ |
| HAL_DBGMCU_EnableDBGSleepMode(); |
| |
| /* Enable debugger EXTI lines */ |
| LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); |
| LL_C2_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); |
| |
| #else |
| /* Disable debugger EXTI lines */ |
| LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48); |
| LL_C2_EXTI_DisableIT_32_63(LL_EXTI_LINE_48); |
| |
| GPIO_InitTypeDef gpio_config = { 0 }; |
| |
| gpio_config.Pull = GPIO_NOPULL; |
| gpio_config.Mode = GPIO_MODE_ANALOG; |
| |
| gpio_config.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_13; |
| __HAL_RCC_GPIOA_CLK_ENABLE(); |
| HAL_GPIO_Init(GPIOA, &gpio_config); |
| __HAL_RCC_GPIOA_CLK_DISABLE(); |
| |
| gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_3; |
| __HAL_RCC_GPIOB_CLK_ENABLE(); |
| HAL_GPIO_Init(GPIOB, &gpio_config); |
| __HAL_RCC_GPIOB_CLK_DISABLE(); |
| |
| /** |
| * Do not keep debugger enabled while in any low power mode |
| */ |
| HAL_DBGMCU_DisableDBGSleepMode(); |
| HAL_DBGMCU_DisableDBGStopMode(); |
| HAL_DBGMCU_DisableDBGStandbyMode(); |
| #endif /* (CFG_DEBUGGER_SUPPORTED == 1) */ |
| |
| #if (CFG_DEBUG_TRACE != 0) |
| DbgTraceInit(); |
| #endif |
| |
| return; |
| } |
| |
| /** |
| * @brief Configure the system for power optimization |
| * |
| * @note This API configures the system to be ready for low power mode |
| * |
| * @param None |
| * @retval None |
| */ |
| static void SystemPower_Config(void) |
| { |
| // Before going to stop or standby modes, do the settings so that system clock and IP80215.4 clock |
| // start on HSI automatically |
| LL_RCC_HSI_EnableAutoFromStop(); |
| |
| /** |
| * Select HSI as system clock source after Wake Up from Stop mode |
| */ |
| LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); |
| |
| /* Initialize low power manager */ |
| UTIL_LPM_Init(); |
| |
| /* Disable low power mode until INIT is complete */ |
| UTIL_LPM_SetOffMode(1 << CFG_LPM_APP, UTIL_LPM_DISABLE); |
| UTIL_LPM_SetStopMode(1 << CFG_LPM_APP, UTIL_LPM_DISABLE); |
| |
| /* Enable RAM1 (because OT instance.o is located here for Concurrent Mode */ |
| LL_C2_AHB1_GRP1_EnableClock(LL_C2_AHB1_GRP1_PERIPH_SRAM1); |
| LL_C2_AHB1_GRP1_EnableClockSleep(LL_C2_AHB1_GRP1_PERIPH_SRAM1); |
| |
| return; |
| } |
| |
| static void appe_Tl_Init(void) |
| { |
| TL_MM_Config_t tl_mm_config; |
| SHCI_TL_HciInitConf_t SHci_Tl_Init_Conf; |
| |
| /**< Reference table initialization */ |
| TL_Init(); |
| |
| /**< System channel initialization */ |
| SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t *) &SystemCmdBuffer; |
| SHci_Tl_Init_Conf.StatusNotCallBack = APPE_SysStatusNot; |
| shci_init(APPE_SysUserEvtRx, (void *) &SHci_Tl_Init_Conf); |
| |
| /**< Memory Manager channel initialization */ |
| tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer; |
| tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer; |
| tl_mm_config.p_AsynchEvtPool = EvtPool; |
| tl_mm_config.AsynchEvtPoolSize = POOL_SIZE; |
| TL_MM_Init(&tl_mm_config); |
| |
| TL_Enable(); |
| |
| return; |
| } |
| |
| static void APPE_SysStatusNot(SHCI_TL_CmdStatus_t status) |
| { |
| UNUSED(status); |
| return; |
| } |
| |
| /** |
| * The type of the payload for a system user event is tSHCI_UserEvtRxParam |
| * When the system event is both : |
| * - a ready event (subevtcode = SHCI_SUB_EVT_CODE_READY) |
| * - reported by the FUS (sysevt_ready_rsp == FUS_FW_RUNNING) |
| * The buffer shall not be released |
| * ( eg ((tSHCI_UserEvtRxParam*)pPayload)->status shall be set to SHCI_TL_UserEventFlow_Disable ) |
| * When the status is not filled, the buffer is released by default |
| */ |
| static void APPE_SysUserEvtRx(void * pPayload) |
| { |
| TL_AsynchEvt_t * p_sys_event; |
| p_sys_event = (TL_AsynchEvt_t *) (((tSHCI_UserEvtRxParam *) pPayload)->pckt->evtserial.evt.payload); |
| |
| switch (p_sys_event->subevtcode) |
| { |
| case SHCI_SUB_EVT_CODE_READY: |
| APPE_SysEvtReadyProcessing(); |
| break; |
| |
| case SHCI_SUB_EVT_ERROR_NOTIF: |
| APPE_SysEvtError((SCHI_SystemErrCode_t) (p_sys_event->payload[0])); |
| break; |
| |
| default: |
| break; |
| } |
| return; |
| } |
| |
| /** |
| * @brief Notify a system error coming from the M0 firmware |
| * @param ErrorCode : errorCode detected by the M0 firmware |
| * |
| * @retval None |
| */ |
| static void APPE_SysEvtError(SCHI_SystemErrCode_t ErrorCode) |
| { |
| switch (ErrorCode) |
| { |
| case ERR_THREAD_LLD_FATAL_ERROR: |
| APP_DBG("** ERR_THREAD : LLD_FATAL_ERROR \n"); |
| break; |
| |
| case ERR_THREAD_UNKNOWN_CMD: |
| APP_DBG("** ERR_THREAD : UNKNOWN_CMD \n"); |
| break; |
| |
| default: |
| APP_DBG("** ERR_THREAD : ErroCode=%d \n", ErrorCode); |
| break; |
| } |
| return; |
| } |
| |
| static void APPE_SysEvtReadyProcessing(void) |
| { |
| /* Traces channel initialization */ |
| TL_TRACES_Init(); |
| |
| /* In the Context of Dynamic Concurrent mode, the Init and start of each stack must be split and executed |
| * in the following order : |
| * APP_BLE_Init : BLE Stack Init until it's ready to start ADV |
| * APP_THREAD_Init_Dyn_1() : Thread Stack Init until it's ready to be configured (default channel, PID, etc...) |
| */ |
| APP_DBG("1- Initialisation of BLE Stack..."); |
| APP_BLE_Init_Dyn_1(); |
| APP_DBG("2- Initialisation of OpenThread Stack. FW info :"); |
| APP_THREAD_Init(); |
| APP_BLE_Init_Dyn_2(); |
| |
| APP_DBG("Start init matter"); |
| GetAppTask().StartAppTask(); |
| |
| #if (CFG_LPM_SUPPORTED == 1) |
| /* Thread stack is initialized, low power mode can be enabled */ |
| UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE); |
| UTIL_LPM_SetStopMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE); |
| #endif |
| |
| return; |
| } |
| |
| static void Led_Init(void) |
| { |
| #if (CFG_LED_SUPPORTED == 1U) |
| /** |
| * Leds Initialization |
| */ |
| |
| #endif |
| |
| return; |
| } |
| |
| static void Button_Init(void) |
| { |
| |
| #if (CFG_BUTTON_SUPPORTED == 1U) |
| /** |
| * Button Initialization |
| */ |
| |
| BSP_PB_Init(BUTTON_USER1, BUTTON_MODE_EXTI); |
| #endif |
| |
| return; |
| } |
| |
| #if (CFG_HW_EXTPA_ENABLED == 1) |
| static void ExtPA_Init(void) |
| { |
| GPIO_InitTypeDef GPIO_InitStruct; |
| |
| // configure the GPIO PB0 in AF6 to be used as RF_TX_MOD_EXT_PA |
| GPIO_InitStruct.Pull = GPIO_NOPULL; |
| GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; |
| GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; |
| GPIO_InitStruct.Alternate = GPIO_AF6_RF_DTB0; |
| GPIO_InitStruct.Pin = GPIO_EXT_PA_TX_PIN; |
| HAL_GPIO_Init(GPIO_EXT_PA_TX_PORT, &GPIO_InitStruct); |
| |
| // configure the GPIO which will be managed by M0 stack to enable Ext PA |
| GPIO_InitStruct.Pull = GPIO_NOPULL; |
| GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; |
| GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; |
| GPIO_InitStruct.Pin = GPIO_EXT_PA_EN_PIN; |
| HAL_GPIO_Init(GPIO_EXT_PA_EN_PORT, &GPIO_InitStruct); |
| |
| // Indicate to M0 which GPIO must be managed |
| SHCI_C2_ExtpaConfig((uint32_t) GPIO_EXT_PA_EN_PORT, GPIO_EXT_PA_EN_PIN, EXT_PA_ENABLED_HIGH, EXT_PA_ENABLED); |
| } |
| #endif /* CFG_HW_EXTPA_ENABLED */ |
| |
| /************************************************************* |
| * |
| * WRAP FUNCTIONS |
| * |
| *************************************************************/ |
| static void PushButtonEvtProcess(void * argument) |
| { |
| UNUSED(argument); |
| for (;;) |
| { |
| /* USER CODE BEGIN SHCI_USER_EVT_PROCESS_1 */ |
| |
| /* USER CODE END SHCI_USER_EVT_PROCESS_1 */ |
| osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); |
| Push_Button_st Message; |
| Message.Pushed_Button = BUTTON_USER1; |
| Message.State = 1; |
| PbCb(&Message); // call matter callback to handle push button |
| /* USER CODE BEGIN SHCI_USER_EVT_PROCESS_2 */ |
| |
| /* USER CODE END SHCI_USER_EVT_PROCESS_2 */ |
| } |
| } |
| |
| static void ShciUserEvtProcess(void * argument) |
| { |
| UNUSED(argument); |
| for (;;) |
| { |
| /* USER CODE BEGIN SHCI_USER_EVT_PROCESS_1 */ |
| |
| /* USER CODE END SHCI_USER_EVT_PROCESS_1 */ |
| // osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); |
| osSemaphoreAcquire(SemShciUserEvtProcessId, osWaitForever); |
| shci_user_evt_proc(); |
| /* USER CODE BEGIN SHCI_USER_EVT_PROCESS_2 */ |
| |
| /* USER CODE END SHCI_USER_EVT_PROCESS_2 */ |
| } |
| } |
| |
| void shci_notify_asynch_evt(void * pdata) |
| { |
| UNUSED(pdata); |
| osSemaphoreRelease(SemShciUserEvtProcessId); |
| return; |
| } |
| |
| void shci_cmd_resp_release(uint32_t flag) |
| { |
| UNUSED(flag); |
| osSemaphoreRelease(SemShciId); |
| return; |
| } |
| |
| void shci_cmd_resp_wait(uint32_t timeout) |
| { |
| UNUSED(timeout); |
| osSemaphoreAcquire(SemShciId, osWaitForever); |
| return; |
| } |
| |
| /* Received trace buffer from M0 */ |
| void TL_TRACES_EvtReceived(TL_EvtPacket_t * hcievt) |
| { |
| #if (CFG_DEBUG_TRACE != 0) |
| /* Call write/print function using DMA from dbg_trace */ |
| /* - Cast to TL_AsynchEvt_t* to get "real" payload (without Sub Evt code 2bytes), |
| - (-2) to size to remove Sub Evt Code */ |
| DbgTraceWrite(1U, (const unsigned char *) ((TL_AsynchEvt_t *) (hcievt->evtserial.evt.payload))->payload, |
| hcievt->evtserial.evt.plen - 2U); |
| #endif /* CFG_DEBUG_TRACE */ |
| /* Release buffer */ |
| TL_MM_EvtDone(hcievt); |
| } |
| /** |
| * @brief Initialization of the trace mechanism |
| * @param None |
| * @retval None |
| */ |
| #if (CFG_DEBUG_TRACE != 0) |
| void DbgOutputInit(void) |
| { |
| #if (CFG_HW_USART1_ENABLED == 1) |
| HW_UART_Init(CFG_DEBUG_TRACE_UART); |
| #endif |
| return; |
| } |
| |
| /** |
| * @brief Management of the traces |
| * @param p_data : data |
| * @param size : size |
| * @param call-back : |
| * @retval None |
| */ |
| void DbgOutputTraces(uint8_t * p_data, uint16_t size, void (*cb)(void)) |
| { |
| HW_UART_Transmit_DMA(CFG_DEBUG_TRACE_UART, p_data, size, cb); |
| |
| return; |
| } |
| #endif |
| |
| /** |
| * @brief This function manage the Push button action |
| * @param GPIO_Pin : GPIO pin which has been activated |
| * @retval None |
| */ |
| void BSP_PB_Callback(Button_TypeDef Button) |
| { |
| switch (Button) |
| { |
| case BUTTON_USER1: |
| APP_DBG("BUTTON 1 PUSHED !"); |
| osThreadFlagsSet(OsPushButtonProcessId, 1); |
| break; |
| |
| case BUTTON_USER2: |
| APP_DBG("BUTTON 2 PUSHED !"); |
| /* Set "Switch Protocol" Task */ |
| break; |
| |
| default: |
| break; |
| } |
| |
| return; |
| } |
| #ifdef __cplusplus |
| } |
| #endif |