blob: f631165467e749460d26f52dcd084f0b83c06b9c [file] [log] [blame]
/* 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