BLE streaming of sensor data working
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_debug.c
|
||||
* @author MCD Application Team
|
||||
* @brief Debug capabilities source file for STM32WPAN Middleware
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 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 ------------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "app_common.h"
|
||||
|
||||
#include "app_debug.h"
|
||||
#include "utilities_common.h"
|
||||
#include "shci.h"
|
||||
#include "tl.h"
|
||||
#include "dbg_trace.h"
|
||||
#include "standby.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
typedef PACKED_STRUCT
|
||||
{
|
||||
GPIO_TypeDef* port;
|
||||
uint16_t pin;
|
||||
uint8_t enable;
|
||||
uint8_t reserved;
|
||||
} APPD_GpioConfig_t;
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
#define GPIO_NBR_OF_RF_SIGNALS 9
|
||||
#define GPIO_CFG_NBR_OF_FEATURES 38
|
||||
#define NBR_OF_TRACES_CONFIG_PARAMETERS 4
|
||||
#define NBR_OF_GENERAL_CONFIG_PARAMETERS 14
|
||||
/**
|
||||
* THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT
|
||||
*/
|
||||
#define BLE_DTB_CFG 0
|
||||
|
||||
/**
|
||||
* System Debug Options flags to be configured with:
|
||||
* - SHCI_C2_DEBUG_OPTIONS_IPCORE_LP
|
||||
* - SHCI_C2_DEBUG_OPTIONS_IPCORE_NO_LP
|
||||
* - SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN
|
||||
* - SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_DIS
|
||||
* which are used to set following configuration bits:
|
||||
* - bit 0: 0: IP BLE core in LP mode 1: IP BLE core in run mode (no LP supported)
|
||||
* - bit 1: 0: CPU2 STOP mode Enable 1: CPU2 STOP mode Disable
|
||||
* - bit [2-7]: bits reserved ( shall be set to 0)
|
||||
*/
|
||||
#define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN)
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig={0, 0, 0, 0};
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_GeneralConfig_t APPD_GeneralConfig={BLE_DTB_CFG, SYS_DBG_CFG1, {0, 0}, 0, 0, 0, 0, 0};
|
||||
|
||||
#ifdef CFG_DEBUG_TRACE_UART
|
||||
#if(CFG_HW_LPUART1_ENABLED == 1)
|
||||
extern void MX_LPUART1_UART_Init(void);
|
||||
#endif
|
||||
#if(CFG_HW_USART1_ENABLED == 1)
|
||||
extern void MX_USART1_UART_Init(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
|
||||
* It provides timing information on the CPU2 activity.
|
||||
* All configuration of (port, pin) is supported for each features and can be selected by the user
|
||||
* depending on the availability
|
||||
*/
|
||||
static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] =
|
||||
{
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ISR - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_TICK - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_CMD_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ACL_DATA_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* SYS_CMD_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* RNG_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVM_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_GENERAL - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_EVT_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_ACL_DATA_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_EVT_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_ACK_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_ACK_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_MEM_MANAGER_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */
|
||||
/* From v1.1.1 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */
|
||||
/* From v1.2.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* PES_ACTIVITY - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* MB_BLE_SEND_EVT - Set on Entry / Reset on Exit */
|
||||
/* From v1.3.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_NO_DELAY - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_STORE_NVM_CB - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_ONGOING - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_COMPLETE - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_CLEANUP - Set on Entry / Reset on Exit */
|
||||
/* From v1.4.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_START - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_EOP - Set on Entry / Reset on Exit */
|
||||
/* From v1.5.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_WRITE - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_ERASE - Set on Entry / Reset on Exit */
|
||||
/* From v1.6.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_RESCHEDULE_EVENT - Set on Entry / Reset on Exit */
|
||||
/* From v1.8.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_LLD_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_LLD_ACK_TX - Set on Entry / Reset on Exit */
|
||||
/* From v1.9.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ASYNCH_EVENT_NACKED - Set on Entry / Reset on Exit */
|
||||
};
|
||||
|
||||
/**
|
||||
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
|
||||
* This table is relevant only for BLE
|
||||
* It provides timing information on BLE RF activity.
|
||||
* New signals may be allocated at any location when requested by ST
|
||||
* The GPIO allocated to each signal depend on the BLE_DTB_CFG value and cannot be changed
|
||||
*/
|
||||
#if( BLE_DTB_CFG == 7)
|
||||
static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] =
|
||||
{
|
||||
{ GPIOB, LL_GPIO_PIN_2, 0, 0}, /* DTB10 - Tx/Rx SPI */
|
||||
{ GPIOB, LL_GPIO_PIN_7, 0, 0}, /* DTB11 - Tx/Tx SPI Clk */
|
||||
{ GPIOA, LL_GPIO_PIN_8, 0, 0}, /* DTB12 - Tx/Rx Ready & SPI Select */
|
||||
{ GPIOA, LL_GPIO_PIN_9, 0, 0}, /* DTB13 - Tx/Rx Start */
|
||||
{ GPIOA, LL_GPIO_PIN_10, 0, 0}, /* DTB14 - FSM0 */
|
||||
{ GPIOA, LL_GPIO_PIN_11, 0, 0}, /* DTB15 - FSM1 */
|
||||
{ GPIOB, LL_GPIO_PIN_8, 0, 0}, /* DTB16 - FSM2 */
|
||||
{ GPIOA, LL_GPIO_PIN_13, 0, 0}, /* DTB17 - FSM3 */
|
||||
{ GPIOA, LL_GPIO_PIN_14, 0, 0}, /* DTB18 - FSM4 */
|
||||
};
|
||||
#endif
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN GV */
|
||||
/* USER CODE END GV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
static void APPD_SetCPU2GpioConfig( void );
|
||||
static void APPD_BleDtbCfg( void );
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void APPD_Init( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_Init */
|
||||
#if (CFG_DEBUGGER_SUPPORTED == 1)
|
||||
/**
|
||||
* Keep debugger enabled while in any low power mode
|
||||
*/
|
||||
HAL_DBGMCU_EnableDBGSleepMode();
|
||||
HAL_DBGMCU_EnableDBGStopMode();
|
||||
|
||||
/***************** ENABLE DEBUGGER *************************************/
|
||||
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
|
||||
|
||||
#else
|
||||
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();
|
||||
|
||||
HAL_DBGMCU_DisableDBGSleepMode();
|
||||
HAL_DBGMCU_DisableDBGStopMode();
|
||||
HAL_DBGMCU_DisableDBGStandbyMode();
|
||||
|
||||
#endif /* (CFG_DEBUGGER_SUPPORTED == 1) */
|
||||
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
DbgTraceInit();
|
||||
#endif
|
||||
|
||||
APPD_SetCPU2GpioConfig( );
|
||||
APPD_BleDtbCfg( );
|
||||
|
||||
/* USER CODE END APPD_Init */
|
||||
return;
|
||||
}
|
||||
|
||||
void APPD_EnableCPU2( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_EnableCPU2 */
|
||||
APPD_GeneralConfig.STBY_DebugGpioaPinList = STBY_DebugGpioaPinList;
|
||||
APPD_GeneralConfig.STBY_DebugGpiobPinList = STBY_DebugGpiobPinList;
|
||||
APPD_GeneralConfig.STBY_DebugGpiocPinList = STBY_DebugGpiocPinList;
|
||||
APPD_GeneralConfig.STBY_DtbGpioaPinList = STBY_DtbGpioaPinList;
|
||||
APPD_GeneralConfig.STBY_DtbGpiobPinList = STBY_DtbGpiobPinList;
|
||||
|
||||
SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket =
|
||||
{
|
||||
{{0,0,0}}, /**< Does not need to be initialized */
|
||||
{(uint8_t *)aGpioConfigList,
|
||||
(uint8_t *)&APPD_TracesConfig,
|
||||
(uint8_t *)&APPD_GeneralConfig,
|
||||
GPIO_CFG_NBR_OF_FEATURES,
|
||||
NBR_OF_TRACES_CONFIG_PARAMETERS,
|
||||
NBR_OF_GENERAL_CONFIG_PARAMETERS}
|
||||
};
|
||||
|
||||
/**< Traces channel initialization */
|
||||
TL_TRACES_Init( );
|
||||
|
||||
/** GPIO DEBUG Initialization */
|
||||
SHCI_C2_DEBUG_Init( &DebugCmdPacket );
|
||||
|
||||
/* USER CODE END APPD_EnableCPU2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
static void APPD_SetCPU2GpioConfig( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_SetCPU2GpioConfig */
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
uint8_t local_loop;
|
||||
uint16_t gpioa_pin_list;
|
||||
uint16_t gpiob_pin_list;
|
||||
uint16_t gpioc_pin_list;
|
||||
gpioa_pin_list = STBY_DebugGpioaPinList;
|
||||
gpiob_pin_list = STBY_DebugGpiobPinList;
|
||||
gpioc_pin_list = STBY_DebugGpiocPinList;
|
||||
|
||||
if(gpioa_pin_list == UINT16_MAX)
|
||||
{
|
||||
gpioa_pin_list = 0;
|
||||
gpiob_pin_list = 0;
|
||||
gpioc_pin_list = 0;
|
||||
|
||||
for(local_loop = 0 ; local_loop < GPIO_CFG_NBR_OF_FEATURES; local_loop++)
|
||||
{
|
||||
if( aGpioConfigList[local_loop].enable != 0)
|
||||
{
|
||||
switch((uint32_t)aGpioConfigList[local_loop].port)
|
||||
{
|
||||
case (uint32_t)GPIOA:
|
||||
gpioa_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
case (uint32_t)GPIOB:
|
||||
gpiob_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
case (uint32_t)GPIOC:
|
||||
gpioc_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STBY_DebugGpioaPinList = gpioa_pin_list;
|
||||
STBY_DebugGpiobPinList = gpiob_pin_list;
|
||||
STBY_DebugGpiocPinList = gpioc_pin_list;
|
||||
}
|
||||
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
|
||||
if(gpioa_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpioa_pin_list;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOA, gpioa_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
if(gpiob_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpiob_pin_list;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOB, gpiob_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
if(gpioc_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpioc_pin_list;
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOC_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOC, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOC, gpioc_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
/* USER CODE END APPD_SetCPU2GpioConfig */
|
||||
return;
|
||||
}
|
||||
|
||||
static void APPD_BleDtbCfg( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_BleDtbCfg */
|
||||
#if (BLE_DTB_CFG != 0)
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
uint8_t local_loop;
|
||||
uint16_t gpioa_pin_list;
|
||||
uint16_t gpiob_pin_list;
|
||||
gpioa_pin_list = STBY_DtbGpioaPinList;
|
||||
gpiob_pin_list = STBY_DtbGpiobPinList;
|
||||
|
||||
if(gpioa_pin_list == UINT16_MAX)
|
||||
{
|
||||
gpioa_pin_list = 0;
|
||||
gpiob_pin_list = 0;
|
||||
|
||||
for(local_loop = 0 ; local_loop < GPIO_NBR_OF_RF_SIGNALS; local_loop++)
|
||||
{
|
||||
if( aRfConfigList[local_loop].enable != 0)
|
||||
{
|
||||
switch((uint32_t)aRfConfigList[local_loop].port)
|
||||
{
|
||||
case (uint32_t)GPIOA:
|
||||
gpioa_pin_list |= aRfConfigList[local_loop].pin;
|
||||
break;
|
||||
case (uint32_t)GPIOB:
|
||||
gpiob_pin_list |= aRfConfigList[local_loop].pin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STBY_DtbGpioaPinList = gpioa_pin_list;
|
||||
STBY_DtbGpiobPinList = gpiob_pin_list;
|
||||
}
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
gpio_config.Alternate = GPIO_AF6_RF_DTB7;
|
||||
|
||||
if(gpioa_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpioa_pin_list;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
}
|
||||
|
||||
if(gpiob_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpiob_pin_list;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
}
|
||||
#else
|
||||
STBY_DtbGpioaPinList = 0;
|
||||
STBY_DtbGpiobPinList = 0;
|
||||
#endif
|
||||
|
||||
/* USER CODE END APPD_BleDtbCfg */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* WRAP FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
void DbgOutputInit( void )
|
||||
{
|
||||
/* USER CODE BEGIN DbgOutputInit */
|
||||
#ifdef CFG_DEBUG_TRACE_UART
|
||||
if (CFG_DEBUG_TRACE_UART == hw_lpuart1)
|
||||
{
|
||||
#if(CFG_HW_LPUART1_ENABLED == 1)
|
||||
MX_LPUART1_UART_Init();
|
||||
#endif
|
||||
}
|
||||
else if (CFG_DEBUG_TRACE_UART == hw_uart1)
|
||||
{
|
||||
#if(CFG_HW_USART1_ENABLED == 1)
|
||||
MX_USART1_UART_Init();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* USER CODE END DbgOutputInit */
|
||||
return;
|
||||
}
|
||||
|
||||
void DbgOutputTraces( uint8_t *p_data, uint16_t size, void (*cb)(void) )
|
||||
{
|
||||
/* USER CODE BEGIN DbgOutputTraces */
|
||||
HW_UART_Transmit_DMA(CFG_DEBUG_TRACE_UART, p_data, size, cb);
|
||||
|
||||
/* USER CODE END DbgOutputTraces */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,588 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_entry.c
|
||||
* @author MCD Application Team
|
||||
* @brief Entry point of the application
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 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_common.h"
|
||||
#include "main.h"
|
||||
#include "app_entry.h"
|
||||
#include "app_ble.h"
|
||||
#include "ble.h"
|
||||
#include "tl.h"
|
||||
#include "stm32_seq.h"
|
||||
#include "shci_tl.h"
|
||||
#include "stm32_lpm.h"
|
||||
#include "app_debug.h"
|
||||
#include "dbg_trace.h"
|
||||
#include "shci.h"
|
||||
#include "otp.h"
|
||||
|
||||
/* Private includes -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4U))
|
||||
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
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 + 255U];
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
|
||||
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private functions prototypes-----------------------------------------------*/
|
||||
static void Config_HSE(void);
|
||||
static void Reset_Device(void);
|
||||
#if (CFG_HW_RESET_BY_FW == 1)
|
||||
static void Reset_IPCC(void);
|
||||
static void Reset_BackupDomain(void);
|
||||
#endif /* CFG_HW_RESET_BY_FW == 1*/
|
||||
static void System_Init(void);
|
||||
static void SystemPower_Config(void);
|
||||
static void appe_Tl_Init(void);
|
||||
static void APPE_SysStatusNot(SHCI_TL_CmdStatus_t status);
|
||||
static void APPE_SysUserEvtRx(void * pPayload);
|
||||
static void APPE_SysEvtReadyProcessing(void * pPayload);
|
||||
static void APPE_SysEvtError(void * pPayload);
|
||||
static void Init_Rtc(void);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void MX_APPE_Config(void)
|
||||
{
|
||||
/**
|
||||
* The OPTVERR flag is wrongly set at power on
|
||||
* It shall be cleared before using any HAL_FLASH_xxx() api
|
||||
*/
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
|
||||
|
||||
/**
|
||||
* Reset some configurations so that the system behave in the same way
|
||||
* when either out of nReset or Power On
|
||||
*/
|
||||
Reset_Device();
|
||||
|
||||
/* Configure HSE Tuning */
|
||||
Config_HSE();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void MX_APPE_Init(void)
|
||||
{
|
||||
System_Init(); /**< System initialization */
|
||||
|
||||
SystemPower_Config(); /**< Configure the system Power Mode */
|
||||
|
||||
HW_TS_Init(hw_ts_InitMode_Full, &hrtc); /**< Initialize the TimerServer */
|
||||
|
||||
/* USER CODE BEGIN APPE_Init_1 */
|
||||
|
||||
/* USER CODE END APPE_Init_1 */
|
||||
appe_Tl_Init(); /* Initialize all transport layers */
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
/* USER CODE END APPE_Init_2 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Init_Smps(void)
|
||||
{
|
||||
#if (CFG_USE_SMPS != 0)
|
||||
/**
|
||||
* Configure and enable SMPS
|
||||
*
|
||||
* The SMPS configuration is not yet supported by CubeMx
|
||||
* when SMPS output voltage is set to 1.4V, the RF output power is limited to 3.7dBm
|
||||
* the SMPS output voltage shall be increased for higher RF output power
|
||||
*/
|
||||
LL_PWR_SMPS_SetStartupCurrent(LL_PWR_SMPS_STARTUP_CURRENT_80MA);
|
||||
LL_PWR_SMPS_SetOutputVoltageLevel(LL_PWR_SMPS_OUTPUT_VOLTAGE_1V40);
|
||||
LL_PWR_SMPS_Enable();
|
||||
#endif /* CFG_USE_SMPS != 0 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Init_Exti(void)
|
||||
{
|
||||
/* Enable IPCC(36), HSEM(38) wakeup interrupts on CPU1 */
|
||||
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_36 | LL_EXTI_LINE_38);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN FD */
|
||||
|
||||
/* USER CODE END FD */
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
static void Reset_Device(void)
|
||||
{
|
||||
#if (CFG_HW_RESET_BY_FW == 1)
|
||||
Reset_BackupDomain();
|
||||
|
||||
Reset_IPCC();
|
||||
#endif /* CFG_HW_RESET_BY_FW == 1 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CFG_HW_RESET_BY_FW == 1)
|
||||
static void Reset_BackupDomain(void)
|
||||
{
|
||||
if ((LL_RCC_IsActiveFlag_PINRST() != FALSE) && (LL_RCC_IsActiveFlag_SFTRST() == FALSE))
|
||||
{
|
||||
HAL_PWR_EnableBkUpAccess(); /**< Enable access to the RTC registers */
|
||||
|
||||
/**
|
||||
* Write twice the value to flush the APB-AHB bridge
|
||||
* This bit shall be written in the register before writing the next one
|
||||
*/
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
|
||||
__HAL_RCC_BACKUPRESET_FORCE();
|
||||
__HAL_RCC_BACKUPRESET_RELEASE();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Reset_IPCC(void)
|
||||
{
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
|
||||
|
||||
LL_C1_IPCC_ClearFlag_CHx(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C2_IPCC_ClearFlag_CHx(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C1_IPCC_DisableTransmitChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C2_IPCC_DisableTransmitChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C1_IPCC_DisableReceiveChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C2_IPCC_DisableReceiveChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CFG_HW_RESET_BY_FW == 1 */
|
||||
|
||||
static void Config_HSE(void)
|
||||
{
|
||||
OTP_ID0_t * p_otp;
|
||||
|
||||
/**
|
||||
* Read HSE_Tuning from OTP
|
||||
*/
|
||||
p_otp = (OTP_ID0_t *) OTP_Read(0);
|
||||
if (p_otp)
|
||||
{
|
||||
LL_RCC_HSE_SetCapacitorTuning(p_otp->hse_tuning);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void System_Init(void)
|
||||
{
|
||||
Init_Smps();
|
||||
|
||||
Init_Exti();
|
||||
|
||||
Init_Rtc();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Init_Rtc(void)
|
||||
{
|
||||
/* Disable RTC registers write protection */
|
||||
LL_RTC_DisableWriteProtection(RTC);
|
||||
|
||||
LL_RTC_WAKEUP_SetClock(RTC, CFG_RTC_WUCKSEL_DIVIDER);
|
||||
|
||||
/* Enable RTC registers write protection */
|
||||
LL_RTC_EnableWriteProtection(RTC);
|
||||
|
||||
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)
|
||||
{
|
||||
/**
|
||||
* 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();
|
||||
/* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
|
||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||
|
||||
#if (CFG_USB_INTERFACE_ENABLE != 0)
|
||||
/**
|
||||
* Enable USB power
|
||||
*/
|
||||
HAL_PWREx_EnableVddUSB();
|
||||
#endif /* CFG_USB_INTERFACE_ENABLE != 0 */
|
||||
/**
|
||||
* Active SRAM retention for standby support
|
||||
*/
|
||||
HAL_PWREx_EnableSRAMRetention();
|
||||
|
||||
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 */
|
||||
UTIL_SEQ_RegTask(1<< CFG_TASK_SYSTEM_HCI_ASYNCH_EVT_ID, UTIL_SEQ_RFU, shci_user_evt_proc);
|
||||
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;
|
||||
WirelessFwInfo_t WirelessInfo;
|
||||
|
||||
p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
|
||||
switch(p_sys_event->subevtcode)
|
||||
{
|
||||
case SHCI_SUB_EVT_CODE_READY:
|
||||
/* Read the firmware version of both the wireless firmware and the FUS */
|
||||
SHCI_GetWirelessFwInfo(&WirelessInfo);
|
||||
APP_DBG_MSG("Wireless Firmware version %d.%d.%d\n", WirelessInfo.VersionMajor, WirelessInfo.VersionMinor, WirelessInfo.VersionSub);
|
||||
APP_DBG_MSG("Wireless Firmware build %d\n", WirelessInfo.VersionReleaseType);
|
||||
APP_DBG_MSG("FUS version %d.%d.%d\n", WirelessInfo.FusVersionMajor, WirelessInfo.FusVersionMinor, WirelessInfo.FusVersionSub);
|
||||
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY\n\r");
|
||||
APPE_SysEvtReadyProcessing(pPayload);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_ERROR_NOTIF:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF \n\r");
|
||||
APPE_SysEvtError(pPayload);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE -- BLE NVM RAM HAS BEEN UPDATED BY CPU2 \n");
|
||||
APP_DBG_MSG(" - StartAddress = %lx , Size = %ld\n",
|
||||
((SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload)->StartAddress,
|
||||
((SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload)->Size);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_START_WRITE:
|
||||
APP_DBG_MSG("==>> SHCI_SUB_EVT_NVM_START_WRITE : NumberOfWords = %ld\n",
|
||||
((SHCI_C2_NvmStartWrite_Evt_t*)p_sys_event->payload)->NumberOfWords);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_END_WRITE:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_NVM_END_WRITE\n\r");
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_START_ERASE:
|
||||
APP_DBG_MSG("==>>SHCI_SUB_EVT_NVM_START_ERASE : NumberOfSectors = %ld\n",
|
||||
((SHCI_C2_NvmStartErase_Evt_t*)p_sys_event->payload)->NumberOfSectors);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_END_ERASE:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_NVM_END_ERASE\n\r");
|
||||
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(void * pPayload)
|
||||
{
|
||||
TL_AsynchEvt_t *p_sys_event;
|
||||
SCHI_SystemErrCode_t *p_sys_error_code;
|
||||
|
||||
p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
p_sys_error_code = (SCHI_SystemErrCode_t*) p_sys_event->payload;
|
||||
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF WITH REASON %x \n\r",(*p_sys_error_code));
|
||||
|
||||
if ((*p_sys_error_code) == ERR_BLE_INIT)
|
||||
{
|
||||
/* Error during BLE stack initialization */
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF WITH REASON - ERR_BLE_INIT \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF WITH REASON - BLE ERROR \n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void APPE_SysEvtReadyProcessing(void * pPayload)
|
||||
{
|
||||
TL_AsynchEvt_t *p_sys_event;
|
||||
SHCI_C2_Ready_Evt_t *p_sys_ready_event;
|
||||
|
||||
SHCI_C2_CONFIG_Cmd_Param_t config_param = {0};
|
||||
uint32_t RevisionID=0;
|
||||
uint32_t DeviceID=0;
|
||||
|
||||
p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
p_sys_ready_event = (SHCI_C2_Ready_Evt_t*) p_sys_event->payload;
|
||||
|
||||
if (p_sys_ready_event->sysevt_ready_rsp == WIRELESS_FW_RUNNING)
|
||||
{
|
||||
/**
|
||||
* The wireless firmware is running on the CPU2
|
||||
*/
|
||||
APP_DBG_MSG(">>== WIRELESS_FW_RUNNING \n");
|
||||
|
||||
/* Traces channel initialization */
|
||||
APPD_EnableCPU2();
|
||||
|
||||
/* Enable all events Notification */
|
||||
config_param.PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE;
|
||||
config_param.EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT3_NVM_START_WRITE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT4_NVM_END_WRITE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT5_NVM_START_ERASE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT6_NVM_END_ERASE_ENABLE;
|
||||
|
||||
/* Read revision identifier */
|
||||
/**
|
||||
* @brief Return the device revision identifier
|
||||
* @note This field indicates the revision of the device.
|
||||
* @rmtoll DBGMCU_IDCODE REV_ID LL_DBGMCU_GetRevisionID
|
||||
* @retval Values between Min_Data=0x00 and Max_Data=0xFFFF
|
||||
*/
|
||||
RevisionID = LL_DBGMCU_GetRevisionID();
|
||||
|
||||
APP_DBG_MSG(">>== DBGMCU_GetRevisionID= %lx \n\r", RevisionID);
|
||||
|
||||
config_param.RevisionID = (uint16_t)RevisionID;
|
||||
|
||||
DeviceID = LL_DBGMCU_GetDeviceID();
|
||||
APP_DBG_MSG(">>== DBGMCU_GetDeviceID= %lx \n\r", DeviceID);
|
||||
config_param.DeviceID = (uint16_t)DeviceID;
|
||||
(void)SHCI_C2_Config(&config_param);
|
||||
|
||||
APP_BLE_Init();
|
||||
UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE);
|
||||
}
|
||||
else if (p_sys_ready_event->sysevt_ready_rsp == FUS_FW_RUNNING)
|
||||
{
|
||||
/**
|
||||
* The FUS firmware is running on the CPU2
|
||||
* In the scope of this application, there should be no case when we get here
|
||||
*/
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY - FUS_FW_RUNNING \n\r");
|
||||
|
||||
/* The packet shall not be released as this is not supported by the FUS */
|
||||
((tSHCI_UserEvtRxParam*)pPayload)->status = SHCI_TL_UserEventFlow_Disable;
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY - UNEXPECTED CASE \n\r");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN FD_LOCAL_FUNCTIONS */
|
||||
|
||||
/* USER CODE END FD_LOCAL_FUNCTIONS */
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* WRAP FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
void HAL_Delay(uint32_t Delay)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t wait = Delay;
|
||||
|
||||
/* Add a freq to guarantee minimum wait */
|
||||
if (wait < HAL_MAX_DELAY)
|
||||
{
|
||||
wait += HAL_GetTickFreq();
|
||||
}
|
||||
|
||||
while ((HAL_GetTick() - tickstart) < wait)
|
||||
{
|
||||
/************************************************************************************
|
||||
* ENTER SLEEP MODE
|
||||
***********************************************************************************/
|
||||
LL_LPM_EnableSleep(); /**< Clear SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif /* __ARMCC_VERSION */
|
||||
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
|
||||
void MX_APPE_Process(void)
|
||||
{
|
||||
/* USER CODE BEGIN MX_APPE_Process_1 */
|
||||
|
||||
/* USER CODE END MX_APPE_Process_1 */
|
||||
UTIL_SEQ_Run(UTIL_SEQ_DEFAULT);
|
||||
/* USER CODE BEGIN MX_APPE_Process_2 */
|
||||
|
||||
/* USER CODE END MX_APPE_Process_2 */
|
||||
}
|
||||
|
||||
void UTIL_SEQ_Idle(void)
|
||||
{
|
||||
#if (CFG_LPM_SUPPORTED == 1)
|
||||
UTIL_LPM_EnterLowPower();
|
||||
#endif /* CFG_LPM_SUPPORTED == 1 */
|
||||
return;
|
||||
}
|
||||
|
||||
void shci_notify_asynch_evt(void* pdata)
|
||||
{
|
||||
UTIL_SEQ_SetTask(1<<CFG_TASK_SYSTEM_HCI_ASYNCH_EVT_ID, CFG_SCH_PRIO_0);
|
||||
return;
|
||||
}
|
||||
|
||||
void shci_cmd_resp_release(uint32_t flag)
|
||||
{
|
||||
UTIL_SEQ_SetEvt(1<< CFG_IDLEEVT_SYSTEM_HCI_CMD_EVT_RSP_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
void shci_cmd_resp_wait(uint32_t timeout)
|
||||
{
|
||||
UTIL_SEQ_WaitEvt(1<< CFG_IDLEEVT_SYSTEM_HCI_CMD_EVT_RSP_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN FD_WRAP_FUNCTIONS */
|
||||
|
||||
/* USER CODE END FD_WRAP_FUNCTIONS */
|
||||
@@ -0,0 +1,888 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_timerserver.c
|
||||
* @author MCD Application Team
|
||||
* @brief Hardware timerserver source file for STM32WPAN Middleware.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 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_common.h"
|
||||
#include "hw_conf.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
TimerID_Free,
|
||||
TimerID_Created,
|
||||
TimerID_Running
|
||||
}TimerIDStatus_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SSR_Read_Requested,
|
||||
SSR_Read_Not_Requested
|
||||
}RequestReadSSR_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WakeupTimerValue_Overpassed,
|
||||
WakeupTimerValue_LargeEnough
|
||||
}WakeupTimerLimitation_Status_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HW_TS_pTimerCb_t pTimerCallBack;
|
||||
uint32_t CounterInit;
|
||||
uint32_t CountLeft;
|
||||
TimerIDStatus_t TimerIDStatus;
|
||||
HW_TS_Mode_t TimerMode;
|
||||
uint32_t TimerProcessID;
|
||||
uint8_t PreviousID;
|
||||
uint8_t NextID;
|
||||
}TimerContext_t;
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define SSR_FORBIDDEN_VALUE 0xFFFFFFFF
|
||||
#define TIMER_LIST_EMPTY 0xFFFF
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* START of Section TIMERSERVER_CONTEXT
|
||||
*/
|
||||
|
||||
static volatile TimerContext_t aTimerContext[CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER];
|
||||
static volatile uint8_t CurrentRunningTimerID;
|
||||
static volatile uint8_t PreviousRunningTimerID;
|
||||
static volatile uint32_t SSRValueOnLastSetup;
|
||||
static volatile WakeupTimerLimitation_Status_t WakeupTimerLimitation;
|
||||
|
||||
/**
|
||||
* END of Section TIMERSERVER_CONTEXT
|
||||
*/
|
||||
|
||||
static uint8_t WakeupTimerDivider;
|
||||
static uint8_t AsynchPrescalerUserConfig;
|
||||
static uint16_t SynchPrescalerUserConfig;
|
||||
static volatile uint16_t MaxWakeupTimerSetup;
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void RestartWakeupCounter(uint16_t Value);
|
||||
static uint16_t ReturnTimeElapsed(void);
|
||||
static void RescheduleTimerList(void);
|
||||
static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR);
|
||||
static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID);
|
||||
static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID);
|
||||
static uint16_t linkTimer(uint8_t TimerID);
|
||||
static uint32_t ReadRtcSsrValue(void);
|
||||
|
||||
__weak void HW_TS_RTC_CountUpdated_AppNot(void);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Read the RTC_SSR value
|
||||
* As described in the reference manual, the RTC_SSR shall be read twice to ensure
|
||||
* reliability of the value
|
||||
* @param None
|
||||
* @retval SSR value read
|
||||
*/
|
||||
static uint32_t ReadRtcSsrValue(void)
|
||||
{
|
||||
uint32_t first_read;
|
||||
uint32_t second_read;
|
||||
|
||||
first_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
|
||||
|
||||
second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
|
||||
|
||||
while(first_read != second_read)
|
||||
{
|
||||
first_read = second_read;
|
||||
|
||||
second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
|
||||
}
|
||||
|
||||
return second_read;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a Timer in the list after the Timer ID specified
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @param RefTimerID: The ID of the Timer to be linked after
|
||||
* @retval None
|
||||
*/
|
||||
static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID)
|
||||
{
|
||||
uint8_t next_id;
|
||||
|
||||
next_id = aTimerContext[RefTimerID].NextID;
|
||||
|
||||
if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
aTimerContext[next_id].PreviousID = TimerID;
|
||||
}
|
||||
aTimerContext[TimerID].NextID = next_id;
|
||||
aTimerContext[TimerID].PreviousID = RefTimerID ;
|
||||
aTimerContext[RefTimerID].NextID = TimerID;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a Timer in the list before the ID specified
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @param RefTimerID: The ID of the Timer to be linked before
|
||||
* @retval None
|
||||
*/
|
||||
static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID)
|
||||
{
|
||||
uint8_t previous_id;
|
||||
|
||||
if(RefTimerID != CurrentRunningTimerID)
|
||||
{
|
||||
previous_id = aTimerContext[RefTimerID].PreviousID;
|
||||
|
||||
aTimerContext[previous_id].NextID = TimerID;
|
||||
aTimerContext[TimerID].NextID = RefTimerID;
|
||||
aTimerContext[TimerID].PreviousID = previous_id ;
|
||||
aTimerContext[RefTimerID].PreviousID = TimerID;
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimerContext[TimerID].NextID = RefTimerID;
|
||||
aTimerContext[RefTimerID].PreviousID = TimerID;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a Timer in the list
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @retval None
|
||||
*/
|
||||
static uint16_t linkTimer(uint8_t TimerID)
|
||||
{
|
||||
uint32_t time_left;
|
||||
uint16_t time_elapsed;
|
||||
uint8_t timer_id_lookup;
|
||||
uint8_t next_id;
|
||||
|
||||
if(CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
/**
|
||||
* No timer in the list
|
||||
*/
|
||||
PreviousRunningTimerID = CurrentRunningTimerID;
|
||||
CurrentRunningTimerID = TimerID;
|
||||
aTimerContext[TimerID].NextID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;
|
||||
|
||||
SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
|
||||
time_elapsed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_elapsed = ReturnTimeElapsed();
|
||||
|
||||
/**
|
||||
* update count of the timer to be linked
|
||||
*/
|
||||
aTimerContext[TimerID].CountLeft += time_elapsed;
|
||||
time_left = aTimerContext[TimerID].CountLeft;
|
||||
|
||||
/**
|
||||
* Search for index where the new timer shall be linked
|
||||
*/
|
||||
if(aTimerContext[CurrentRunningTimerID].CountLeft <= time_left)
|
||||
{
|
||||
/**
|
||||
* Search for the ID after the first one
|
||||
*/
|
||||
timer_id_lookup = CurrentRunningTimerID;
|
||||
next_id = aTimerContext[timer_id_lookup].NextID;
|
||||
while((next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[next_id].CountLeft <= time_left))
|
||||
{
|
||||
timer_id_lookup = aTimerContext[timer_id_lookup].NextID;
|
||||
next_id = aTimerContext[timer_id_lookup].NextID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link after the ID
|
||||
*/
|
||||
LinkTimerAfter(TimerID, timer_id_lookup);
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* Link before the first ID
|
||||
*/
|
||||
LinkTimerBefore(TimerID, CurrentRunningTimerID);
|
||||
PreviousRunningTimerID = CurrentRunningTimerID;
|
||||
CurrentRunningTimerID = TimerID;
|
||||
}
|
||||
}
|
||||
|
||||
return time_elapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a Timer from the list
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @param RequestReadSSR: Request to read the SSR register or not
|
||||
* @retval None
|
||||
*/
|
||||
static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR)
|
||||
{
|
||||
uint8_t previous_id;
|
||||
uint8_t next_id;
|
||||
|
||||
if(TimerID == CurrentRunningTimerID)
|
||||
{
|
||||
PreviousRunningTimerID = CurrentRunningTimerID;
|
||||
CurrentRunningTimerID = aTimerContext[TimerID].NextID;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_id = aTimerContext[TimerID].PreviousID;
|
||||
next_id = aTimerContext[TimerID].NextID;
|
||||
|
||||
aTimerContext[previous_id].NextID = aTimerContext[TimerID].NextID;
|
||||
if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
aTimerContext[next_id].PreviousID = aTimerContext[TimerID].PreviousID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer is out of the list
|
||||
*/
|
||||
aTimerContext[TimerID].TimerIDStatus = TimerID_Created;
|
||||
|
||||
if((CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (RequestReadSSR == SSR_Read_Requested))
|
||||
{
|
||||
SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the number of ticks counted by the wakeuptimer since it has been started
|
||||
* @note The API is reading the SSR register to get how many ticks have been counted
|
||||
* since the time the timer has been started
|
||||
* @param None
|
||||
* @retval Time expired in Ticks
|
||||
*/
|
||||
static uint16_t ReturnTimeElapsed(void)
|
||||
{
|
||||
uint32_t return_value;
|
||||
uint32_t wrap_counter;
|
||||
|
||||
if(SSRValueOnLastSetup != SSR_FORBIDDEN_VALUE)
|
||||
{
|
||||
return_value = ReadRtcSsrValue(); /**< Read SSR register first */
|
||||
|
||||
if (SSRValueOnLastSetup >= return_value)
|
||||
{
|
||||
return_value = SSRValueOnLastSetup - return_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrap_counter = SynchPrescalerUserConfig - return_value;
|
||||
return_value = SSRValueOnLastSetup + wrap_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* At this stage, ReturnValue holds the number of ticks counted by SSR
|
||||
* Need to translate in number of ticks counted by the Wakeuptimer
|
||||
*/
|
||||
return_value = return_value*AsynchPrescalerUserConfig;
|
||||
return_value = return_value >> WakeupTimerDivider;
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = 0;
|
||||
}
|
||||
|
||||
return (uint16_t)return_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the wakeup counter
|
||||
* @note The API is writing the counter value so that the value is decreased by one to cope with the fact
|
||||
* the interrupt is generated with 1 extra clock cycle (See RefManuel)
|
||||
* It assumes all condition are met to be allowed to write the wakeup counter
|
||||
* @param Value: Value to be written in the counter
|
||||
* @retval None
|
||||
*/
|
||||
static void RestartWakeupCounter(uint16_t Value)
|
||||
{
|
||||
/**
|
||||
* The wakeuptimer has been disabled in the calling function to reduce the time to poll the WUTWF
|
||||
* FLAG when the new value will have to be written
|
||||
* __HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc);
|
||||
*/
|
||||
|
||||
if(Value == 0)
|
||||
{
|
||||
SSRValueOnLastSetup = ReadRtcSsrValue();
|
||||
|
||||
/**
|
||||
* Simulate that the Timer expired
|
||||
*/
|
||||
HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((Value > 1) ||(WakeupTimerDivider != 1))
|
||||
{
|
||||
Value -= 1;
|
||||
}
|
||||
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == RESET);
|
||||
|
||||
/**
|
||||
* make sure to clear the flags after checking the WUTWF.
|
||||
* It takes 2 RTCCLK between the time the WUTE bit is disabled and the
|
||||
* time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
|
||||
* Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
|
||||
* due to the autoreload feature
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
|
||||
|
||||
MODIFY_REG(RTC->WUTR, RTC_WUTR_WUT, Value);
|
||||
|
||||
/**
|
||||
* Update the value here after the WUTWF polling that may take some time
|
||||
*/
|
||||
SSRValueOnLastSetup = ReadRtcSsrValue();
|
||||
|
||||
__HAL_RTC_WAKEUPTIMER_ENABLE(&hrtc); /**< Enable the Wakeup Timer */
|
||||
|
||||
HW_TS_RTC_CountUpdated_AppNot();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reschedule the list of timer
|
||||
* @note 1) Update the count left for each timer in the list
|
||||
* 2) Setup the wakeuptimer
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void RescheduleTimerList(void)
|
||||
{
|
||||
uint8_t localTimerID;
|
||||
uint32_t timecountleft;
|
||||
uint16_t wakeup_timer_value;
|
||||
uint16_t time_elapsed;
|
||||
|
||||
/**
|
||||
* The wakeuptimer is disabled now to reduce the time to poll the WUTWF
|
||||
* FLAG when the new value will have to be written
|
||||
*/
|
||||
if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
|
||||
{
|
||||
/**
|
||||
* Wait for the flag to be back to 0 when the wakeup timer is enabled
|
||||
*/
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == SET);
|
||||
}
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); /**< Disable the Wakeup Timer */
|
||||
|
||||
localTimerID = CurrentRunningTimerID;
|
||||
|
||||
/**
|
||||
* Calculate what will be the value to write in the wakeuptimer
|
||||
*/
|
||||
timecountleft = aTimerContext[localTimerID].CountLeft;
|
||||
|
||||
/**
|
||||
* Read how much has been counted
|
||||
*/
|
||||
time_elapsed = ReturnTimeElapsed();
|
||||
|
||||
if(timecountleft < time_elapsed )
|
||||
{
|
||||
/**
|
||||
* There is no tick left to count
|
||||
*/
|
||||
wakeup_timer_value = 0;
|
||||
WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(timecountleft > (time_elapsed + MaxWakeupTimerSetup))
|
||||
{
|
||||
/**
|
||||
* The number of tick left is greater than the Wakeuptimer maximum value
|
||||
*/
|
||||
wakeup_timer_value = MaxWakeupTimerSetup;
|
||||
|
||||
WakeupTimerLimitation = WakeupTimerValue_Overpassed;
|
||||
}
|
||||
else
|
||||
{
|
||||
wakeup_timer_value = timecountleft - time_elapsed;
|
||||
WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* update ticks left to be counted for each timer
|
||||
*/
|
||||
while(localTimerID != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
if (aTimerContext[localTimerID].CountLeft < time_elapsed)
|
||||
{
|
||||
aTimerContext[localTimerID].CountLeft = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimerContext[localTimerID].CountLeft -= time_elapsed;
|
||||
}
|
||||
localTimerID = aTimerContext[localTimerID].NextID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write next count
|
||||
*/
|
||||
RestartWakeupCounter(wakeup_timer_value);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/* Public functions ----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* For all public interface except that may need write access to the RTC, the RTC
|
||||
* shall be unlock at the beginning and locked at the output
|
||||
* In order to ease maintainability, the unlock is done at the top and the lock at then end
|
||||
* in case some new implementation is coming in the future
|
||||
*/
|
||||
|
||||
void HW_TS_RTC_Wakeup_Handler(void)
|
||||
{
|
||||
HW_TS_pTimerCb_t ptimer_callback;
|
||||
uint32_t timer_process_id;
|
||||
uint8_t local_current_running_timer_id;
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
/**
|
||||
* Disable the Wakeup Timer
|
||||
* This may speed up a bit the processing to wait the timer to be disabled
|
||||
* The timer is still counting 2 RTCCLK
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc);
|
||||
|
||||
local_current_running_timer_id = CurrentRunningTimerID;
|
||||
|
||||
if(aTimerContext[local_current_running_timer_id].TimerIDStatus == TimerID_Running)
|
||||
{
|
||||
ptimer_callback = aTimerContext[local_current_running_timer_id].pTimerCallBack;
|
||||
timer_process_id = aTimerContext[local_current_running_timer_id].TimerProcessID;
|
||||
|
||||
/**
|
||||
* It should be good to check whether the TimeElapsed is greater or not than the tick left to be counted
|
||||
* However, due to the inaccuracy of the reading of the time elapsed, it may return there is 1 tick
|
||||
* to be left whereas the count is over
|
||||
* A more secure implementation has been done with a flag to state whereas the full count has been written
|
||||
* in the wakeuptimer or not
|
||||
*/
|
||||
if(WakeupTimerLimitation != WakeupTimerValue_Overpassed)
|
||||
{
|
||||
if(aTimerContext[local_current_running_timer_id].TimerMode == hw_ts_Repeated)
|
||||
{
|
||||
UnlinkTimer(local_current_running_timer_id, SSR_Read_Not_Requested);
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
HW_TS_Start(local_current_running_timer_id, aTimerContext[local_current_running_timer_id].CounterInit);
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
HW_TS_Stop(local_current_running_timer_id);
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
}
|
||||
|
||||
HW_TS_RTC_Int_AppNot(timer_process_id, local_current_running_timer_id, ptimer_callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
RescheduleTimerList();
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* We should never end up in this case
|
||||
* However, if due to any bug in the timer server this is the case, the mistake may not impact the user.
|
||||
* We could just clean the interrupt flag and get out from this unexpected interrupt
|
||||
*/
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == RESET);
|
||||
|
||||
/**
|
||||
* make sure to clear the flags after checking the WUTWF.
|
||||
* It takes 2 RTCCLK between the time the WUTE bit is disabled and the
|
||||
* time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
|
||||
* Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
|
||||
* due to the autoreload feature
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *phrtc)
|
||||
{
|
||||
uint8_t loop;
|
||||
uint32_t localmaxwakeuptimersetup;
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
SET_BIT(RTC->CR, RTC_CR_BYPSHAD);
|
||||
|
||||
/**
|
||||
* Readout the user config
|
||||
*/
|
||||
WakeupTimerDivider = (4 - ((uint32_t)(READ_BIT(RTC->CR, RTC_CR_WUCKSEL))));
|
||||
|
||||
AsynchPrescalerUserConfig = (uint8_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_A) >> (uint32_t)POSITION_VAL(RTC_PRER_PREDIV_A)) + 1;
|
||||
|
||||
SynchPrescalerUserConfig = (uint16_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_S)) + 1;
|
||||
|
||||
/**
|
||||
* Margin is taken to avoid wrong calculation when the wrap around is there and some
|
||||
* application interrupts may have delayed the reading
|
||||
*/
|
||||
localmaxwakeuptimersetup = ((((SynchPrescalerUserConfig - 1)*AsynchPrescalerUserConfig) - CFG_HW_TS_RTC_HANDLER_MAX_DELAY) >> WakeupTimerDivider);
|
||||
|
||||
if(localmaxwakeuptimersetup >= 0xFFFF)
|
||||
{
|
||||
MaxWakeupTimerSetup = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxWakeupTimerSetup = (uint16_t)localmaxwakeuptimersetup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure EXTI module
|
||||
*/
|
||||
LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
|
||||
LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
|
||||
|
||||
if(TimerInitMode == hw_ts_InitMode_Full)
|
||||
{
|
||||
WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
|
||||
SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
|
||||
|
||||
/**
|
||||
* Initialize the timer server
|
||||
*/
|
||||
for(loop = 0; loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; loop++)
|
||||
{
|
||||
aTimerContext[loop].TimerIDStatus = TimerID_Free;
|
||||
}
|
||||
|
||||
CurrentRunningTimerID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; /**< Set ID to non valid value */
|
||||
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); /**< Disable the Wakeup Timer */
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
|
||||
__HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hrtc, RTC_IT_WUT); /**< Enable interrupt in RTC module */
|
||||
}
|
||||
else
|
||||
{
|
||||
if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTF) != RESET)
|
||||
{
|
||||
/**
|
||||
* Simulate that the Timer expired
|
||||
*/
|
||||
HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
HAL_NVIC_SetPriority(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO); /**< Set NVIC priority */
|
||||
HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pftimeout_handler)
|
||||
{
|
||||
HW_TS_ReturnStatus_t localreturnstatus;
|
||||
uint8_t loop = 0;
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
while((loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[loop].TimerIDStatus != TimerID_Free))
|
||||
{
|
||||
loop++;
|
||||
}
|
||||
|
||||
if(loop != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
aTimerContext[loop].TimerIDStatus = TimerID_Created;
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
aTimerContext[loop].TimerProcessID = TimerProcessID;
|
||||
aTimerContext[loop].TimerMode = TimerMode;
|
||||
aTimerContext[loop].pTimerCallBack = pftimeout_handler;
|
||||
*pTimerId = loop;
|
||||
|
||||
localreturnstatus = hw_ts_Successful;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
localreturnstatus = hw_ts_Failed;
|
||||
}
|
||||
|
||||
return(localreturnstatus);
|
||||
}
|
||||
|
||||
void HW_TS_Delete(uint8_t timer_id)
|
||||
{
|
||||
HW_TS_Stop(timer_id);
|
||||
|
||||
aTimerContext[timer_id].TimerIDStatus = TimerID_Free; /**< release ID */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_TS_Stop(uint8_t timer_id)
|
||||
{
|
||||
uint8_t localcurrentrunningtimerid;
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Disable NVIC */
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
|
||||
{
|
||||
UnlinkTimer(timer_id, SSR_Read_Requested);
|
||||
localcurrentrunningtimerid = CurrentRunningTimerID;
|
||||
|
||||
if(localcurrentrunningtimerid == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
/**
|
||||
* List is empty
|
||||
*/
|
||||
|
||||
/**
|
||||
* Disable the timer
|
||||
*/
|
||||
if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
|
||||
{
|
||||
/**
|
||||
* Wait for the flag to be back to 0 when the wakeup timer is enabled
|
||||
*/
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == SET);
|
||||
}
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); /**< Disable the Wakeup Timer */
|
||||
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == RESET);
|
||||
|
||||
/**
|
||||
* make sure to clear the flags after checking the WUTWF.
|
||||
* It takes 2 RTCCLK between the time the WUTE bit is disabled and the
|
||||
* time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
|
||||
* Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
|
||||
* due to the autoreload feature
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
|
||||
}
|
||||
else if(PreviousRunningTimerID != localcurrentrunningtimerid)
|
||||
{
|
||||
RescheduleTimerList();
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_TS_Start(uint8_t timer_id, uint32_t timeout_ticks)
|
||||
{
|
||||
uint16_t time_elapsed;
|
||||
uint8_t localcurrentrunningtimerid;
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
|
||||
{
|
||||
HW_TS_Stop( timer_id );
|
||||
}
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Disable NVIC */
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
aTimerContext[timer_id].TimerIDStatus = TimerID_Running;
|
||||
|
||||
aTimerContext[timer_id].CountLeft = timeout_ticks;
|
||||
aTimerContext[timer_id].CounterInit = timeout_ticks;
|
||||
|
||||
time_elapsed = linkTimer(timer_id);
|
||||
|
||||
localcurrentrunningtimerid = CurrentRunningTimerID;
|
||||
|
||||
if(PreviousRunningTimerID != localcurrentrunningtimerid)
|
||||
{
|
||||
RescheduleTimerList();
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimerContext[timer_id].CountLeft -= time_elapsed;
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t HW_TS_RTC_ReadLeftTicksToCount(void)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
uint16_t return_value, auro_reload_value, elapsed_time_value;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
|
||||
{
|
||||
auro_reload_value = (uint32_t)(READ_BIT(RTC->WUTR, RTC_WUTR_WUT));
|
||||
|
||||
elapsed_time_value = ReturnTimeElapsed();
|
||||
|
||||
if(auro_reload_value > elapsed_time_value)
|
||||
{
|
||||
return_value = auro_reload_value - elapsed_time_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = TIMER_LIST_EMPTY;
|
||||
}
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
__weak void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack)
|
||||
{
|
||||
pTimerCallBack();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "main.h"
|
||||
#include "dma.h"
|
||||
#include "ipcc.h"
|
||||
#include "rf.h"
|
||||
#include "rtc.h"
|
||||
#include "tim.h"
|
||||
#include "usart.h"
|
||||
@@ -28,6 +29,9 @@
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include <stdbool.h>
|
||||
#include "common_blesvc.h"
|
||||
#include "custom_stm.h"
|
||||
#include "stm32_seq.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
@@ -65,8 +69,26 @@ uint8_t uart_rx_data[1024];
|
||||
uint8_t uart_tx_data[1] = {'R'};
|
||||
bool ready_for_data = false;
|
||||
|
||||
uint8_t notify_buffer[128];
|
||||
|
||||
volatile bool do_notify = false;
|
||||
void SendNotifyTask(void) {
|
||||
if (!do_notify) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
//memcpy(notify_buffer, uart_rx_data, sizeof(notify_buffer));
|
||||
Custom_STM_App_Update_Char(
|
||||
CUSTOM_STM_ARRREAD,
|
||||
uart_rx_data + i * 128
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
HAL_GPIO_TogglePin(GPIOA, LED4_Pin);
|
||||
//memcpy(notify_buffer, uart_rx_data, sizeof(notify_buffer));// do second half later
|
||||
UTIL_SEQ_SetTask(1<<CFG_TASK_SEND_NOTIFY, UTIL_SEQ_RFU);
|
||||
// Process data here or something
|
||||
HAL_UART_Receive_DMA(&huart1, uart_rx_data, sizeof(uart_rx_data));
|
||||
HAL_UART_Transmit_DMA(&huart1, uart_tx_data, sizeof(uart_tx_data));
|
||||
@@ -95,6 +117,8 @@ int main(void)
|
||||
|
||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||||
HAL_Init();
|
||||
/* Config code for STM32_WPAN (HSE Tuning must be done before system clock configuration) */
|
||||
MX_APPE_Config();
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
@@ -119,19 +143,25 @@ int main(void)
|
||||
MX_RTC_Init();
|
||||
MX_USART1_UART_Init();
|
||||
MX_TIM2_Init();
|
||||
MX_RF_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Init code for STM32_WPAN */
|
||||
MX_APPE_Init();
|
||||
|
||||
/* Infinite loop */
|
||||
/* USER CODE BEGIN WHILE */
|
||||
HAL_TIM_Base_Start_IT(&htim2);
|
||||
UTIL_SEQ_RegTask(1<<CFG_TASK_SEND_NOTIFY, UTIL_SEQ_RFU, SendNotifyTask);
|
||||
HAL_Delay(1000); // Give the l452 time to start up
|
||||
HAL_UART_Receive_DMA(&huart1, uart_rx_data, sizeof(uart_rx_data));
|
||||
HAL_UART_Transmit_DMA(&huart1, uart_tx_data, sizeof(uart_tx_data));
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE END WHILE */
|
||||
MX_APPE_Process();
|
||||
|
||||
/* USER CODE BEGIN 3 */
|
||||
}
|
||||
@@ -202,7 +232,8 @@ void PeriphCommonClock_Config(void)
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS;
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP;
|
||||
PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_LSE;
|
||||
PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
|
||||
PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf.c
|
||||
* @brief This file provides code for the configuration
|
||||
* of the RF instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 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 "rf.h"
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* RF init function */
|
||||
void MX_RF_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN RF_Init 0 */
|
||||
|
||||
/* USER CODE END RF_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN RF_Init 1 */
|
||||
|
||||
/* USER CODE END RF_Init 1 */
|
||||
/* USER CODE BEGIN RF_Init 2 */
|
||||
|
||||
/* USER CODE END RF_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
|
||||
@@ -42,8 +42,8 @@ void MX_RTC_Init(void)
|
||||
*/
|
||||
hrtc.Instance = RTC;
|
||||
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
|
||||
hrtc.Init.AsynchPrediv = 127;
|
||||
hrtc.Init.SynchPrediv = 255;
|
||||
hrtc.Init.AsynchPrediv = CFG_RTC_ASYNCH_PRESCALER;
|
||||
hrtc.Init.SynchPrediv = CFG_RTC_SYNCH_PRESCALER;
|
||||
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
|
||||
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
|
||||
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file standby.c
|
||||
* @author MCD Application Team
|
||||
* @brief Specific code for standby low power mode
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 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 "main.h"
|
||||
#include "app_entry.h"
|
||||
#include "app_common.h"
|
||||
#include "app_debug.h"
|
||||
#include "standby.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
uint32_t STBY_BackupMSP;
|
||||
uint32_t STBY_BackupIpccC1MR;
|
||||
uint32_t STBY_BackupVTOR;
|
||||
|
||||
uint32_t STBY_BootStatus;
|
||||
uint16_t STBY_DebugGpioaPinList = UINT16_MAX;
|
||||
uint16_t STBY_DebugGpiobPinList = UINT16_MAX;
|
||||
uint16_t STBY_DebugGpiocPinList = UINT16_MAX;
|
||||
uint16_t STBY_DtbGpioaPinList = UINT16_MAX;
|
||||
uint16_t STBY_DtbGpiobPinList = UINT16_MAX;
|
||||
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void STBY_TriggerIT(void);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/*******************************************************************************
|
||||
* This part may be updated by the user
|
||||
******************************************************************************/
|
||||
|
||||
void STBY_AppHwSave(void)
|
||||
{
|
||||
/* In this function HW parameters lost in standby can de saved.
|
||||
All RAM memory is in retention */
|
||||
/* USER CODE BEGIN STBY_AppHwSave_1 */
|
||||
|
||||
/* USER CODE END STBY_AppHwSave_1 */
|
||||
return;
|
||||
}
|
||||
|
||||
void STBY_AppHwRestore(void)
|
||||
{
|
||||
/* USER CODE BEGIN STBY_AppHwRestore_1 */
|
||||
|
||||
/* USER CODE END STBY_AppHwRestore_1 */
|
||||
|
||||
HAL_Init();
|
||||
HAL_ResumeTick();
|
||||
|
||||
/* In this user section add MX init functions present in main.c, except MX_RTC_Init() */
|
||||
/* USER CODE BEGIN STBY_AppHwRestore_2 */
|
||||
|
||||
/* USER CODE END STBY_AppHwRestore_2 */
|
||||
|
||||
STBY_TriggerIT();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Do not update code from this limit.
|
||||
******************************************************************************/
|
||||
|
||||
void STBY_SysHwSave(void)
|
||||
{
|
||||
STBY_BackupIpccC1MR = READ_REG(IPCC->C1MR);
|
||||
STBY_BackupVTOR = SCB->VTOR;
|
||||
|
||||
/* USER CODE BEGIN STBY_SysHwSave_1 */
|
||||
|
||||
/* USER CODE END STBY_SysHwSave_1 */
|
||||
return;
|
||||
}
|
||||
|
||||
void STBY_SysHwRestore(void)
|
||||
{
|
||||
/* USER CODE BEGIN STBY_SysHwRestore_1 */
|
||||
|
||||
/* USER CODE END STBY_SysHwRestore_1 */
|
||||
APPD_Init();
|
||||
|
||||
Init_Smps();
|
||||
Init_Exti();
|
||||
HAL_Init();
|
||||
|
||||
WRITE_REG(SCB->VTOR, STBY_BackupVTOR);
|
||||
|
||||
HW_IPCC_Init();
|
||||
WRITE_REG(IPCC->C1MR, STBY_BackupIpccC1MR);
|
||||
|
||||
if( !LL_HSEM_1StepLock( HSEM, CFG_HW_RCC_SEMID ) )
|
||||
{
|
||||
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
|
||||
LL_HSEM_ReleaseLock( HSEM, CFG_HW_RCC_SEMID, 0 );
|
||||
}
|
||||
LL_HSEM_ReleaseLock( HSEM, CFG_HW_PWR_STANDBY_SEMID, 0 );
|
||||
|
||||
HW_TS_Init(hw_ts_InitMode_Limited, &hrtc);
|
||||
|
||||
LL_PWR_EnableSRAM2Retention();
|
||||
|
||||
/* USER CODE BEGIN STBY_SysHwRestore_2 */
|
||||
|
||||
/* USER CODE END STBY_SysHwRestore_2 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t STBY_BootManager(void)
|
||||
{
|
||||
#if ( CFG_LPM_STANDBY_SUPPORTED != 0 )
|
||||
__HAL_RCC_HSEM_CLK_ENABLE();
|
||||
while( LL_HSEM_1StepLock( HSEM, CFG_HW_PWR_STANDBY_SEMID ) );
|
||||
|
||||
/* If a reset other than standby occurs, perform a full reset cycle */
|
||||
if( (LL_RCC_IsActiveFlag_IWDGRST() != FALSE) ||
|
||||
(LL_RCC_IsActiveFlag_WWDGRST() != FALSE) ||
|
||||
(LL_RCC_IsActiveFlag_BORRST() != FALSE) ||
|
||||
(LL_RCC_IsActiveFlag_LPWRRST() != FALSE) ||
|
||||
(LL_RCC_IsActiveFlag_OBLRST() != FALSE) ||
|
||||
(LL_RCC_IsActiveFlag_PINRST() != FALSE) ||
|
||||
(LL_RCC_IsActiveFlag_SFTRST() != FALSE) )
|
||||
{
|
||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
|
||||
}
|
||||
|
||||
if( __HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET )
|
||||
{
|
||||
__disable_irq( );
|
||||
|
||||
STBY_BootStatus = 1;
|
||||
}else{
|
||||
STBY_BootStatus = 0;
|
||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_C2SB);
|
||||
LL_HSEM_ReleaseLock( HSEM, CFG_HW_PWR_STANDBY_SEMID, 0 );
|
||||
}
|
||||
#else
|
||||
STBY_BootStatus = 0;
|
||||
#endif
|
||||
|
||||
return STBY_BootStatus;
|
||||
}
|
||||
|
||||
static void STBY_TriggerIT(void)
|
||||
{
|
||||
/* If system has been woken-up by an RTC alarm,
|
||||
* a software event must be generated to trigger the IT.
|
||||
* NVIC and EXTI must be reconfigured properly before triggering the event.
|
||||
*/
|
||||
if((__HAL_RTC_ALARM_GET_FLAG((RTC_HandleTypeDef *)&hrtc, RTC_FLAG_ALRAF) != 0) ||
|
||||
(__HAL_RTC_ALARM_GET_FLAG((RTC_HandleTypeDef *)&hrtc, RTC_FLAG_ALRBF) != 0) )
|
||||
{
|
||||
__HAL_RTC_ALARM_EXTI_GENERATE_SWIT();
|
||||
}
|
||||
|
||||
/* If system has been woken-up by a wake up pin,
|
||||
* a software event must be generated to trigger the IT.
|
||||
* NVIC and EXTI must be reconfigured properly before triggering the event.
|
||||
*/
|
||||
if(HAL_PWREx_GetWakeupFlag(PWR_FLAG_WUF1) != 0)
|
||||
{
|
||||
if( (LL_SYSCFG_GetEXTISource(LL_SYSCFG_EXTI_LINE0) == LL_SYSCFG_EXTI_PORTA) )
|
||||
{
|
||||
if(((READ_BIT(PWR->CR4, PWR_CR4_WP1) >> PWR_CR4_WP1_Pos) == 0) &&
|
||||
(LL_EXTI_IsEnabledRisingTrig_0_31(LL_EXTI_LINE_0) == 1) )
|
||||
{
|
||||
LL_EXTI_GenerateSWI_0_31(LL_EXTI_LINE_0);
|
||||
}
|
||||
if(((READ_BIT(PWR->CR4, PWR_CR4_WP1) >> PWR_CR4_WP1_Pos) == 1) &&
|
||||
(LL_EXTI_IsEnabledFallingTrig_0_31(LL_EXTI_LINE_0) == 1) )
|
||||
{
|
||||
LL_EXTI_GenerateSWI_0_31(LL_EXTI_LINE_0);
|
||||
}
|
||||
}
|
||||
HAL_PWREx_ClearWakeupFlag(PWR_FLAG_WUF1);
|
||||
}
|
||||
|
||||
if(HAL_PWREx_GetWakeupFlag(PWR_FLAG_WUF4) != 0)
|
||||
{
|
||||
if( (LL_SYSCFG_GetEXTISource(LL_SYSCFG_EXTI_LINE2) == LL_SYSCFG_EXTI_PORTA) )
|
||||
{
|
||||
if(((READ_BIT(PWR->CR4, PWR_CR4_WP4) >> PWR_CR4_WP4_Pos) == 0) &&
|
||||
(LL_EXTI_IsEnabledRisingTrig_0_31(LL_EXTI_LINE_2) == 1) )
|
||||
{
|
||||
LL_EXTI_GenerateSWI_0_31(LL_EXTI_LINE_2);
|
||||
}
|
||||
if(((READ_BIT(PWR->CR4, PWR_CR4_WP4) >> PWR_CR4_WP4_Pos) == 1) &&
|
||||
(LL_EXTI_IsEnabledFallingTrig_0_31(LL_EXTI_LINE_2) == 1) )
|
||||
{
|
||||
LL_EXTI_GenerateSWI_0_31(LL_EXTI_LINE_2);
|
||||
}
|
||||
}
|
||||
HAL_PWREx_ClearWakeupFlag(PWR_FLAG_WUF4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
***************************************************************************************
|
||||
* @file stm32_lpm_if.c
|
||||
* @author MCD Application Team
|
||||
* @brief Low layer function to enter/exit low power modes (stop, sleep).
|
||||
***************************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 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 "stm32_lpm_if.h"
|
||||
#include "stm32_lpm.h"
|
||||
#include "app_conf.h"
|
||||
#include "main.h"
|
||||
#include "standby.h"
|
||||
/* USER CODE BEGIN include */
|
||||
|
||||
/* USER CODE END include */
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
const struct UTIL_LPM_Driver_s UTIL_PowerDriver =
|
||||
{
|
||||
PWR_EnterSleepMode,
|
||||
PWR_ExitSleepMode,
|
||||
|
||||
PWR_EnterStopMode,
|
||||
PWR_ExitStopMode,
|
||||
|
||||
PWR_EnterOffMode,
|
||||
PWR_ExitOffMode,
|
||||
};
|
||||
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
|
||||
void CPUcontextSave(void); /* this function is implemented in startup assembly file */
|
||||
void SystemClock_Config(void);
|
||||
void PeriphCommonClock_Config(void);
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void Switch_On_HSI(void);
|
||||
static void EnterLowPower(void);
|
||||
static void ExitLowPower(void);
|
||||
#if (CFG_LPM_STANDBY_SUPPORTED != 0)
|
||||
static void ExitLowPower_standby(void);
|
||||
#endif
|
||||
/* USER CODE BEGIN Private_Function_Prototypes */
|
||||
|
||||
/* USER CODE END Private_Function_Prototypes */
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Typedef */
|
||||
|
||||
/* USER CODE END Private_Typedef */
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Define */
|
||||
|
||||
/* USER CODE END Private_Define */
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Macro */
|
||||
|
||||
/* USER CODE END Private_Macro */
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Variables */
|
||||
|
||||
/* USER CODE END Private_Variables */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Enters Low Power Off Mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterOffMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_EnterOffMode_1 */
|
||||
|
||||
/* USER CODE END PWR_EnterOffMode_1 */
|
||||
/**
|
||||
* The systick should be disabled for the same reason than when the device enters stop mode because
|
||||
* at this time, the device may enter either OffMode or StopMode.
|
||||
*/
|
||||
HAL_SuspendTick();
|
||||
__HAL_RCC_CLEAR_RESET_FLAGS();
|
||||
|
||||
EnterLowPower();
|
||||
|
||||
/************************************************************************************
|
||||
* ENTER OFF MODE
|
||||
***********************************************************************************/
|
||||
/*
|
||||
* There is no risk to clear all the WUF here because in the current implementation, this API is called
|
||||
* in critical section. If an interrupt occurs while in that critical section before that point,
|
||||
* the flag is set and will be cleared here but the system will not enter Off Mode
|
||||
* because an interrupt is pending in the NVIC. The ISR will be executed when moving out
|
||||
* of this critical section
|
||||
*/
|
||||
LL_PWR_ClearFlag_WU();
|
||||
|
||||
LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);
|
||||
|
||||
LL_LPM_EnableDeepSleep(); /**< Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif
|
||||
|
||||
#if (CFG_LPM_STANDBY_SUPPORTED != 0)
|
||||
LL_EXTI_EnableRisingTrig_32_63(LL_EXTI_LINE_40);
|
||||
LL_EXTI_EnableEvent_32_63(LL_EXTI_LINE_40);
|
||||
|
||||
STBY_AppHwSave();
|
||||
STBY_SysHwSave();
|
||||
|
||||
CPUcontextSave();/* this function will call WFI instruction */
|
||||
#endif
|
||||
|
||||
/* USER CODE BEGIN PWR_EnterOffMode_2 */
|
||||
|
||||
/* USER CODE END PWR_EnterOffMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Off Mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitOffMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_ExitOffMode_1 */
|
||||
|
||||
/* USER CODE END PWR_ExitOffMode_1 */
|
||||
#if (CFG_LPM_STANDBY_SUPPORTED != 0)
|
||||
if(STBY_BootStatus != 0)
|
||||
{
|
||||
STBY_SysHwRestore();
|
||||
ExitLowPower_standby();
|
||||
STBY_AppHwRestore();
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitLowPower();
|
||||
}
|
||||
#endif
|
||||
/* USER CODE BEGIN PWR_ExitOffMode_2 */
|
||||
|
||||
/* USER CODE END PWR_ExitOffMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Stop Mode
|
||||
* @note ARM exists the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterStopMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_EnterStopMode_1 */
|
||||
|
||||
/* USER CODE END PWR_EnterStopMode_1 */
|
||||
/**
|
||||
* When HAL_DBGMCU_EnableDBGStopMode() is called to keep the debugger active in Stop Mode,
|
||||
* the systick shall be disabled otherwise the cpu may crash when moving out from stop mode
|
||||
*
|
||||
* When in production, the HAL_DBGMCU_EnableDBGStopMode() is not called so that the device can reach best power consumption
|
||||
* However, the systick should be disabled anyway to avoid the case when it is about to expire at the same time the device enters
|
||||
* stop mode (this will abort the Stop Mode entry).
|
||||
*/
|
||||
HAL_SuspendTick();
|
||||
|
||||
/**
|
||||
* This function is called from CRITICAL SECTION
|
||||
*/
|
||||
EnterLowPower();
|
||||
|
||||
/************************************************************************************
|
||||
* ENTER STOP MODE
|
||||
***********************************************************************************/
|
||||
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1);
|
||||
|
||||
LL_LPM_EnableDeepSleep(); /**< Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif
|
||||
|
||||
__WFI();
|
||||
|
||||
/* USER CODE BEGIN PWR_EnterStopMode_2 */
|
||||
|
||||
/* USER CODE END PWR_EnterStopMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Stop Mode
|
||||
* @note Enable the pll at 32MHz
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitStopMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_ExitStopMode_1 */
|
||||
|
||||
/* USER CODE END PWR_ExitStopMode_1 */
|
||||
/**
|
||||
* This function is called from CRITICAL SECTION
|
||||
*/
|
||||
ExitLowPower();
|
||||
|
||||
HAL_ResumeTick();
|
||||
/* USER CODE BEGIN PWR_ExitStopMode_2 */
|
||||
|
||||
/* USER CODE END PWR_ExitStopMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Sleep Mode
|
||||
* @note ARM exits the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterSleepMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_EnterSleepMode_1 */
|
||||
|
||||
/* USER CODE END PWR_EnterSleepMode_1 */
|
||||
|
||||
HAL_SuspendTick();
|
||||
|
||||
/************************************************************************************
|
||||
* ENTER SLEEP MODE
|
||||
***********************************************************************************/
|
||||
LL_LPM_EnableSleep(); /**< Clear SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif
|
||||
|
||||
__WFI();
|
||||
/* USER CODE BEGIN PWR_EnterSleepMode_2 */
|
||||
|
||||
/* USER CODE END PWR_EnterSleepMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Sleep Mode
|
||||
* @note ARM exits the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitSleepMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_ExitSleepMode_1 */
|
||||
|
||||
/* USER CODE END PWR_ExitSleepMode_1 */
|
||||
HAL_ResumeTick();
|
||||
/* USER CODE BEGIN PWR_ExitSleepMode_2 */
|
||||
|
||||
/* USER CODE END PWR_ExitSleepMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Weak CPUcontextSave function definition to implement in startup file.
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
__WEAK void CPUcontextSave(void)
|
||||
{
|
||||
#if (CFG_LPM_STANDBY_SUPPORTED != 0)
|
||||
/*
|
||||
* If you are here, you have to update your startup_stm32wb15xx_cm4.s file to
|
||||
* implement CPUcontextSave function like done in latest STM32CubeWB package
|
||||
* into STM32WB15 BLE applications.
|
||||
*/
|
||||
Error_Handler();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
/**
|
||||
* @brief Setup the system to enter either stop or off mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void EnterLowPower(void)
|
||||
{
|
||||
/**
|
||||
* This function is called from CRITICAL SECTION
|
||||
*/
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID));
|
||||
|
||||
if (! LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID))
|
||||
{
|
||||
if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB())
|
||||
{
|
||||
/* Release ENTRY_STOP_MODE semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||
|
||||
Switch_On_HSI();
|
||||
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Switch_On_HSI();
|
||||
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_0);
|
||||
}
|
||||
|
||||
/* Release RCC semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore the system to exit stop mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void ExitLowPower(void)
|
||||
{
|
||||
/* Release ENTRY_STOP_MODE semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID));
|
||||
|
||||
if(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
|
||||
{
|
||||
/* Restore the clock configuration of the application in this user section */
|
||||
/* USER CODE BEGIN ExitLowPower_1 */
|
||||
|
||||
/* USER CODE END ExitLowPower_1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the application is not running on HSE restore the clock configuration in this user section */
|
||||
/* USER CODE BEGIN ExitLowPower_2 */
|
||||
|
||||
/* USER CODE END ExitLowPower_2 */
|
||||
}
|
||||
#if (CFG_LPM_STANDBY_SUPPORTED != 0)
|
||||
|
||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
|
||||
#endif
|
||||
|
||||
/* Release RCC semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CFG_LPM_STANDBY_SUPPORTED != 0)
|
||||
/**
|
||||
* @brief Restore the system to exit standby mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void ExitLowPower_standby(void)
|
||||
{
|
||||
/* Release ENTRY_STOP_MODE semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID));
|
||||
/* USER CODE BEGIN ExitLowPower_standby */
|
||||
|
||||
/* USER CODE END ExitLowPower_standby */
|
||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
|
||||
|
||||
/* Release RCC semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Switch the system clock on HSI
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void Switch_On_HSI(void)
|
||||
{
|
||||
LL_RCC_HSI_Enable();
|
||||
while(!LL_RCC_HSI_IsReady());
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
|
||||
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI);
|
||||
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI);
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Private_Functions */
|
||||
|
||||
/* USER CODE END Private_Functions */
|
||||
|
||||
Reference in New Issue
Block a user