Initial snapshot: Aliro applet, harness, Nucleo NFC10A1 reader port
Three components, all bench-validated to varying depths: - applet/: CSA Aliro v1.0 Java Card applet for J3R180. AUTH0 + AUTH1 expedited-standard flow end-to-end green via PC/SC bench reader (aliro-bench-test). Userland AES-256-GCM and HMAC-SHA-256 layered on top of J3R180's primitives because the card lacks both natively. P-256 curve params seeded explicitly per J3R180's quirk. - harness/: Python orchestrator (aliro-trustgen, aliro-personalize, aliro-bench-test) for trust-bundle generation, card personalization via PersonalizationApplet, and PC/SC AUTH0+AUTH1 transactions. 126 pytest cases passing. - reader/STM32CubeExpansion_ALIRO_V1_0_0/: ST X-CUBE-ALIRO V1.0.0 with our NFC10A1 port (NUCLEO-U545RE-Q + X-NUCLEO-NFC10A1, ST25R200 shared with NFC09A1). nfc10-only/ project, NFC10A1 BSP shim, ALIRO_TRUST_OVERRIDE include into vendor's provisioning.c, and an ALIRO_APDU_TRACE wrapper around demoTransceiveBlocking. Boots, detects the J3R180, completes SELECT + AUTH0; AUTH1 currently fails with RFAL ERR_PROTO (0xB) — under investigation, see docs/plans/2026-04-20-nucleo-nfc10a1-port.md and bench-notes/. Excluded: x-cube-aliro.zip vendor archive, harness/.venv, build dirs, generated aliro_trust.h (contains private reader scalar), all PEMs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file adv_trace_usart_if.c
|
||||
* @author MCD Application Team
|
||||
* @brief : Source file for interfacing the stm32_adv_trace to hardware
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_conf.h"
|
||||
#include "stm32_adv_trace.h"
|
||||
#include "adv_trace_usart_if.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* list all the driver interface used by the trace application. */
|
||||
const UTIL_ADV_TRACE_Driver_s UTIL_TraceDriver =
|
||||
{
|
||||
UART_Init,
|
||||
UART_DeInit,
|
||||
UART_StartRx,
|
||||
UART_TransmitDMA
|
||||
};
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* Whether the UART should be in RX after a Transmit */
|
||||
uint8_t receive_after_transmit = 0;
|
||||
|
||||
/* Buffer to receive 1 character */
|
||||
static uint8_t cCharRx;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
static void (*TxCpltCallback) ( void * );
|
||||
static void (*RxCpltCallback) ( uint8_t * pData, uint16_t iSize, uint8_t cError );
|
||||
|
||||
static void UsartIf_TxCpltCallback ( UART_HandleTypeDef *huart );
|
||||
static void UsartIf_RxCpltCallback ( UART_HandleTypeDef *huart );
|
||||
static IRQn_Type get_IRQn_Type_from_DMA_HandleTypeDef (DMA_HandleTypeDef * hDmaHandler );
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_Init( void (*pCallbackFunction)(void *))
|
||||
{
|
||||
TxCpltCallback = pCallbackFunction;
|
||||
|
||||
LOG_UART_HANDLER.TxCpltCallback = UsartIf_TxCpltCallback;
|
||||
|
||||
return UTIL_ADV_TRACE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_DeInit( void )
|
||||
{
|
||||
HAL_StatusTypeDef eResult;
|
||||
|
||||
eResult = HAL_UART_DeInit( &LOG_UART_HANDLER );
|
||||
if ( eResult != HAL_OK )
|
||||
{
|
||||
LOG_UART_HANDLER.TxCpltCallback = NULL;
|
||||
return UTIL_ADV_TRACE_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return UTIL_ADV_TRACE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_StartRx( void (*pCallbackFunction)(uint8_t * pData, uint16_t iSize, uint8_t cError ) )
|
||||
{
|
||||
/* Configure UART in Receive mode */
|
||||
HAL_UART_Receive_IT( &LOG_UART_HANDLER, &cCharRx, 1 );
|
||||
LOG_UART_HANDLER.RxCpltCallback = &UsartIf_RxCpltCallback;
|
||||
|
||||
if ( pCallbackFunction != NULL )
|
||||
{
|
||||
RxCpltCallback = pCallbackFunction;
|
||||
}
|
||||
|
||||
return UTIL_ADV_TRACE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_TransmitDMA ( uint8_t * pData, uint16_t iSize )
|
||||
{
|
||||
UTIL_ADV_TRACE_Status_t eStatus = UTIL_ADV_TRACE_OK;
|
||||
HAL_StatusTypeDef eResult;
|
||||
IRQn_Type eUseDmaTx;
|
||||
|
||||
eUseDmaTx = get_IRQn_Type_from_DMA_HandleTypeDef( LOG_UART_HANDLER.hdmatx );
|
||||
|
||||
if ( ( eUseDmaTx == GPDMA1_Channel0_IRQn ) || ( eUseDmaTx == GPDMA1_Channel1_IRQn ) ||
|
||||
( eUseDmaTx == GPDMA1_Channel2_IRQn ) || ( eUseDmaTx == GPDMA1_Channel3_IRQn ) ||
|
||||
( eUseDmaTx == GPDMA1_Channel4_IRQn ) || ( eUseDmaTx == GPDMA1_Channel5_IRQn ) ||
|
||||
( eUseDmaTx == GPDMA1_Channel6_IRQn ) || ( eUseDmaTx == GPDMA1_Channel7_IRQn ) )
|
||||
{
|
||||
eResult = HAL_UART_Transmit_DMA( &LOG_UART_HANDLER, pData, iSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
eResult = HAL_UART_Transmit_IT( &LOG_UART_HANDLER, pData, iSize );
|
||||
}
|
||||
|
||||
if ( eResult != HAL_OK )
|
||||
{
|
||||
eStatus = UTIL_ADV_TRACE_HW_ERROR;
|
||||
}
|
||||
|
||||
/* Check whether the UART should return in Receiver mode */
|
||||
if ( receive_after_transmit )
|
||||
{
|
||||
HAL_UART_Receive_IT( &LOG_UART_HANDLER, &cCharRx, 1 );
|
||||
}
|
||||
|
||||
return eStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void UsartIf_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* ADV Trace callback */
|
||||
TxCpltCallback(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void UsartIf_RxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
RxCpltCallback( &cCharRx, 1, 0 );
|
||||
HAL_UART_Receive_IT( &LOG_UART_HANDLER, &cCharRx, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* The purpose of this function is to match a DMA_HandleTypeDef as key with the corresponding IRQn_Type as value.
|
||||
*
|
||||
* TAKE CARE : in case of an invalid parameter or e.g. an usart/lpuart not initialized, this will lead to hard fault.
|
||||
* it is up to the user to ensure the serial link is in a valid state.
|
||||
*/
|
||||
static IRQn_Type get_IRQn_Type_from_DMA_HandleTypeDef( DMA_HandleTypeDef * hDmaHandler )
|
||||
{
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel0 )
|
||||
{ return GPDMA1_Channel0_IRQn; }
|
||||
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel1 )
|
||||
{ return GPDMA1_Channel1_IRQn; }
|
||||
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel2 )
|
||||
{ return GPDMA1_Channel2_IRQn; }
|
||||
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel3 )
|
||||
{ return GPDMA1_Channel3_IRQn; }
|
||||
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel4 )
|
||||
{ return GPDMA1_Channel4_IRQn; }
|
||||
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel5 )
|
||||
{ return GPDMA1_Channel5_IRQn; }
|
||||
|
||||
if (hDmaHandler->Instance == GPDMA1_Channel6 )
|
||||
{ return GPDMA1_Channel6_IRQn; }
|
||||
|
||||
if ( hDmaHandler->Instance == GPDMA1_Channel7 )
|
||||
{ return GPDMA1_Channel7_IRQn; }
|
||||
|
||||
/* Values from (-1) to (-15) are already in used. This value isn't used so it should be safe.
|
||||
So, if you see this value, it means you used an invalid DMA handler as input. */
|
||||
return (IRQn_Type)(-666);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usart_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief : Header file for stm32_adv_trace interface file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef USART_IF_H
|
||||
#define USART_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32_adv_trace.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 */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
/**
|
||||
* @brief Init the UART and associated DMA.
|
||||
* @param cb tx function callback.
|
||||
* @return @ref UTIL_ADV_TRACE_Status_t
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_Init(void (*cb)(void *));
|
||||
|
||||
/**
|
||||
* @brief DeInit the UART and associated DMA.
|
||||
* @return @ref UTIL_ADV_TRACE_Status_t
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_DeInit(void);
|
||||
|
||||
/**
|
||||
* @brief send buffer to UART using DMA
|
||||
* @param pdata data to be sent
|
||||
* @param size of buffer p_data to be sent
|
||||
* @return @ref UTIL_ADV_TRACE_Status_t
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_TransmitDMA(uint8_t *pdata, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief start Rx process
|
||||
* @param cb callback to receive the data
|
||||
* @return @ref UTIL_ADV_TRACE_Status_t
|
||||
*/
|
||||
UTIL_ADV_TRACE_Status_t UART_StartRx(void (*cb)(uint8_t *pdata, uint16_t size, uint8_t error));
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USART_IF_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_bsp.h
|
||||
* @author MCD Application Team
|
||||
* @brief Interface to manage BSP.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef APP_BSP_H
|
||||
#define APP_BSP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_conf.h"
|
||||
#include "stm32_rtos.h"
|
||||
|
||||
#ifdef STM32WBA55xx
|
||||
#ifdef CFG_BSP_ON_DISCOVERY
|
||||
#include "stm32wba55g_discovery.h"
|
||||
#if (CFG_LCD_SUPPORTED == 1)
|
||||
#include "stm32wba55g_discovery_lcd.h"
|
||||
#include "stm32_lcd.h"
|
||||
#endif /* (CFG_LCD_SUPPORTED == 1) */
|
||||
#endif /* CFG_BSP_ON_DISCOVERY */
|
||||
#endif /* STM32WBA55xx */
|
||||
|
||||
#ifdef STM32WBA65xx
|
||||
#ifdef CFG_BSP_ON_DISCOVERY
|
||||
#include "stm32wba65i_discovery.h"
|
||||
#if (CFG_LCD_SUPPORTED == 1)
|
||||
#include "stm32wba65i_discovery_lcd.h"
|
||||
#include "stm32_lcd.h"
|
||||
#endif /* (CFG_LCD_SUPPORTED == 1) */
|
||||
#endif /* CFG_BSP_ON_DISCOVERY */
|
||||
#endif /* STM32WBA65xx */
|
||||
|
||||
#ifdef CFG_BSP_ON_CEB
|
||||
#ifdef STM32WBA5Mxx
|
||||
#include "b_wba5m_wpan.h"
|
||||
#endif
|
||||
#ifdef STM32WBA6Mxx
|
||||
#include "b_wba6m_wpan.h"
|
||||
#endif
|
||||
#endif /* CFG_BSP_ON_CEB */
|
||||
#ifdef CFG_BSP_ON_NUCLEO
|
||||
#include "stm32wbaxx_nucleo.h"
|
||||
#endif /* CFG_BSP_ON_CEB */
|
||||
|
||||
#ifdef CFG_COAP_MSG
|
||||
#include "coap.h"
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#if (CFG_LCD_SUPPORTED == 1)
|
||||
#define LCD1 (0u)
|
||||
#endif /* (CFG_LCD_SUPPORTED == 1) */
|
||||
|
||||
#if (defined CFG_BSP_ON_DISCOVERY) && (defined STM32WBA65xx)
|
||||
/* No Led Blue on Discovery for STM32WBA65I. Replaced by Red Led */
|
||||
#define LED_BLUE LED_RED
|
||||
#endif /* (defined CFG_BSP_ON_DISCOVERY) && (defined STM32WBA65xx) */
|
||||
|
||||
#if (CFG_JOYSTICK_SUPPORTED == 1)
|
||||
#define JOYSTICK_USE_AS_JOYSTICK (0u) /* When Joystick is not 'none', call according 'Joystick Action' every JOYSTICK_PRESS_SAMPLE_MS. */
|
||||
#define JOYSTICK_USE_AS_BUTTON (1u) /* When Joystick is pressed, call according 'Joystick Action' one time. */
|
||||
#define JOYSTICK_USE_AS_BUTTON_WITH_TIME (2u) /* When Joystick is pressed, it wait the release or the end of JOYSTICK_LONG_PRESS_THRESHOLD_MS
|
||||
before call according 'Joystick Action'. */
|
||||
#define JOYSTICK_USE_AS_CHANGE (3u) /* When Joystcik is pressed according 'Joystick Action' is called. When the Joystick is released, 'JoystickNoneAction' is called. */
|
||||
#define JOYSTICK_USE_AS_MATTER (4u) /* When Joystick is pressed, according 'Joystick Action' is called. When the Joystick is released or the end
|
||||
of JOYSTICK_LONG_PRESS_THRESHOLD_MS occurs, according 'Joystick Action' is called (same as when pressed). */
|
||||
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
#ifdef CFG_COAP_MSG
|
||||
extern uint32_t APP_Thread_TransmitPeriod_ms;
|
||||
extern uint32_t APP_Thread_CoapPayloadLength_byte;
|
||||
extern otCoapType APP_Thread_CoapType;
|
||||
#endif
|
||||
|
||||
#if (CFG_BUTTON_SUPPORTED == 1)
|
||||
#ifdef CFG_BSP_ON_THREADX
|
||||
extern TX_SEMAPHORE ButtonB1Semaphore, ButtonB2Semaphore, ButtonB3Semaphore;
|
||||
#endif /* CFG_BSP_ON_THREADX */
|
||||
#ifdef CFG_BSP_ON_FREERTOS
|
||||
extern osSemaphoreId_t ButtonB1Semaphore, ButtonB2Semaphore, ButtonB3Semaphore;
|
||||
#endif /* CFG_BSP_ON_FREERTOS */
|
||||
#endif /* (CFG_BUTTON_SUPPORTED == 1) */
|
||||
|
||||
#if (CFG_JOYSTICK_SUPPORTED == 1)
|
||||
#ifdef CFG_BSP_ON_THREADX
|
||||
extern TX_SEMAPHORE JoystickUpSemaphore, JoystickRightSemaphore, JoystickDownSemaphore, JoystickLeftSemaphore, JoystickSelectSemaphore, JoystickNoneSemaphore;
|
||||
#endif /* CFG_BSP_ON_THREADX */
|
||||
#ifdef CFG_BSP_ON_FREERTOS
|
||||
extern osSemaphoreId_t JoystickUpSemaphore, JoystickRightSemaphore, JoystickDownSemaphore, JoystickLeftSemaphore, JoystickSelectSemaphore, JoystickNoneSemaphore;
|
||||
#endif /* CFG_BSP_ON_FREERTOS */
|
||||
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */
|
||||
|
||||
/* Exported macros ------------------------------------------------------------*/
|
||||
#if ( CFG_LED_SUPPORTED == 1 )
|
||||
#define APP_BSP_LED_On( LED ) BSP_LED_On( LED )
|
||||
#define APP_BSP_LED_Off( LED ) BSP_LED_Off( LED )
|
||||
#define APP_BSP_LED_Toggle( LED ) BSP_LED_Toggle( LED )
|
||||
#else /* ( CFG_LED_SUPPORTED == 1 ) */
|
||||
#define APP_BSP_LED_On( LED )
|
||||
#define APP_BSP_LED_Off( LED )
|
||||
#define APP_BSP_LED_Toggle( LED )
|
||||
#endif /* ( CFG_LED_SUPPORTED == 1 ) */
|
||||
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void APP_BSP_Init ( void );
|
||||
void APP_BSP_PostIdle ( void );
|
||||
void APP_BSP_StandbyExit ( void );
|
||||
uint8_t APP_BSP_SerialCmdExecute ( uint8_t * pRxBuffer, uint16_t iRxBufferSize );
|
||||
|
||||
#if (CFG_LED_SUPPORTED == 1)
|
||||
void APP_BSP_LedInit ( void );
|
||||
|
||||
#endif /* (CFG_LED_SUPPORTED == 1) */
|
||||
#if (CFG_LCD_SUPPORTED == 1)
|
||||
void APP_BSP_LcdInit ( void );
|
||||
|
||||
#endif /* (CFG_LCD_SUPPORTED == 1) */
|
||||
#if ( CFG_BUTTON_SUPPORTED == 1 )
|
||||
void APP_BSP_ButtonInit ( void );
|
||||
|
||||
uint8_t APP_BSP_ButtonIsLongPressed ( uint16_t btnIdx );
|
||||
void APP_BSP_SetButtonIsLongPressed ( uint16_t btnIdx );
|
||||
|
||||
void APP_BSP_Button1Action ( void );
|
||||
void APP_BSP_Button2Action ( void );
|
||||
void APP_BSP_Button3Action ( void );
|
||||
|
||||
void BSP_PB_Callback ( Button_TypeDef button );
|
||||
|
||||
#endif /* ( CFG_BUTTON_SUPPORTED == 1 ) */
|
||||
#if ( CFG_JOYSTICK_SUPPORTED == 1 )
|
||||
void APP_BSP_JoystickInit ( void );
|
||||
uint8_t APP_BSP_JoystickIsLongPressed ( void );
|
||||
uint8_t APP_BSP_JoystickIsShortReleased ( void );
|
||||
uint8_t APP_BSP_JoystickIsInitialPress ( void );
|
||||
|
||||
void APP_BSP_JoystickUpAction ( void );
|
||||
void APP_BSP_JoystickRightAction ( void );
|
||||
void APP_BSP_JoystickDownAction ( void );
|
||||
void APP_BSP_JoystickLeftAction ( void );
|
||||
void APP_BSP_JoystickSelectAction ( void );
|
||||
void APP_BSP_JoystickNoneAction ( void );
|
||||
|
||||
void BSP_JOY_Callback ( JOY_TypeDef joyNb, JOYPin_TypeDef joyPin );
|
||||
|
||||
#endif /* CFG_JOYSTICK_SUPPORTED */
|
||||
|
||||
void APP_BSP_CliInit ( void );
|
||||
void APP_BSP_CoapMsgRateAction ( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*APP_BSP_H */
|
||||
@@ -0,0 +1,562 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw.h
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the interface of STM32 HW drivers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef HW_H__
|
||||
#define HW_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stm32wbaxx.h"
|
||||
#include "app_conf.h"
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* General
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef CFG_HW_ERROR_OFFSET
|
||||
#define CFG_HW_ERROR_OFFSET 0
|
||||
#endif
|
||||
|
||||
/* Return values definition */
|
||||
enum
|
||||
{
|
||||
HW_OK = 0,
|
||||
HW_BUSY = 1
|
||||
};
|
||||
|
||||
/*
|
||||
* HW_Init
|
||||
*
|
||||
* This function must be called once after reset before calling any of the
|
||||
* other HW functions.
|
||||
*/
|
||||
extern void HW_Init( void );
|
||||
|
||||
/*
|
||||
* HW_Delay
|
||||
*
|
||||
* This function is used internally for minimum delays.
|
||||
* The input is given in microseconds and must be strictly higher than 0 (> 0)
|
||||
* and lower than 16000000 (= 16 s).
|
||||
* Be careful that the actual delay can be higher than the one programmed
|
||||
* if the function is interrupted.
|
||||
* The function is declared "weak" and can be overloaded by the user.
|
||||
*/
|
||||
extern void HW_Delay( uint32_t delay_us );
|
||||
|
||||
/*
|
||||
* HW_GetPackageType
|
||||
*
|
||||
* Returns the package type (cf Package Data Register in STM32WB UM)
|
||||
*/
|
||||
extern uint32_t HW_GetPackageType( void );
|
||||
|
||||
/*
|
||||
* HW_Config_HSE
|
||||
*/
|
||||
void HW_Config_HSE( uint8_t hsetune );
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* AES
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Mode definitions used for HW_AES_SetKey() function */
|
||||
enum
|
||||
{
|
||||
HW_AES_DEC = 0,
|
||||
HW_AES_ENC = 1,
|
||||
HW_AES_REV = 2,
|
||||
HW_AES_SWAP = 4
|
||||
};
|
||||
|
||||
extern int CRYP_MutexTake(void);
|
||||
extern int CRYP_MutexRelease(void);
|
||||
|
||||
/*
|
||||
* HW_AES_Enable
|
||||
*
|
||||
* Enables the AES hardware block.
|
||||
* If the AES was already in use, the function does nothing and returns 0;
|
||||
* otherwise it returns 1.
|
||||
* Be careful: no re-entrance is ensured for the HW_AES functions
|
||||
*/
|
||||
extern int HW_AES_Enable( void );
|
||||
|
||||
/*
|
||||
* HW_AES_SetKey
|
||||
*
|
||||
* Sets the key used for encryption/decryption.
|
||||
* The "mode" parameter must be set to HW_AES_ENC for encryption and to
|
||||
* HW_AES_DEC for decryption. It can be or-ed with HW_AES_REV for a reveresd
|
||||
* oreder of key bytes, and with HW_AES_SWAP to use data byte swapping mode.
|
||||
*/
|
||||
extern void HW_AES_SetKey( uint32_t mode,
|
||||
const uint8_t* key );
|
||||
|
||||
/*
|
||||
* HW_AES_Crypt
|
||||
*
|
||||
* Encrypts/decrypts the 16-byte input data ("input"). Result is written in the
|
||||
* 16-byte buffer ("output") allocated by the user.
|
||||
*/
|
||||
extern void HW_AES_Crypt( const uint32_t* input,
|
||||
uint32_t* output );
|
||||
|
||||
/*
|
||||
* HW_AES_Crypt
|
||||
*
|
||||
* Encrypts/decrypts the 16-byte input data ("input").
|
||||
* Result is written in the 16-byte buffer ("output") allocated by the user.
|
||||
*
|
||||
* Note : input & output are 8 bits aligned.
|
||||
*/
|
||||
extern void HW_AES_Crypt8( const uint8_t* input, uint8_t* output );
|
||||
|
||||
/*
|
||||
* HW_AES_Disable
|
||||
*
|
||||
* Disables the AES hardware block.
|
||||
*/
|
||||
extern void HW_AES_Disable( void );
|
||||
|
||||
/*
|
||||
* HW_AES_InitCcm
|
||||
*
|
||||
* Initilaizes AES for CCM encryption (decrypt = 0) or decryption (decrypt = 1)
|
||||
* Note: B0 and B1 4-word blocks must be provided by user.
|
||||
*
|
||||
*/
|
||||
extern void HW_AES_InitCcm( uint8_t decrypt,
|
||||
const uint8_t* key,
|
||||
const uint32_t* b0,
|
||||
const uint32_t* b1 );
|
||||
|
||||
/*
|
||||
* HW_AES_EndCcm
|
||||
*
|
||||
* Completes CCM processing by computing the authentication tag
|
||||
*
|
||||
*/
|
||||
extern void HW_AES_EndCcm( uint8_t tag_length,
|
||||
uint8_t* tag );
|
||||
|
||||
/*
|
||||
* HW_AES_SetLast
|
||||
*
|
||||
* Function used in CCM processing to indicate the last block of data in
|
||||
* case of decryption
|
||||
*
|
||||
*/
|
||||
extern void HW_AES_SetLast( uint8_t left_length );
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* PKA
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
extern int PKA_MutexTake(void);
|
||||
extern int PKA_MutexRelease(void);
|
||||
|
||||
/*
|
||||
* HW_PKA_Enable
|
||||
*
|
||||
* Enables the PKA hardware block.
|
||||
* If the driver is already in used, the function returns 0 immediately.
|
||||
* If the PKA semaphore is available, this function locks the PKA semaphore,
|
||||
* otherwise it returns 0.
|
||||
* Then, when PKA semaphore is locked, the function enables PKA security,
|
||||
* PKA clock and the block itself.
|
||||
* This function must not be directly called when using P-256 elliptic curve
|
||||
* dedicated functions.
|
||||
* Be careful: no re-entrance is ensured for the HW_PKA functions
|
||||
*/
|
||||
extern int HW_PKA_Enable( void );
|
||||
|
||||
/*
|
||||
* HW_PKA_WriteSingleInput
|
||||
*
|
||||
* Writes one single word into the PKA memory.
|
||||
* This function must not be directly called when using P-256 elliptic curve
|
||||
* dedicated functions.
|
||||
*/
|
||||
extern void HW_PKA_WriteSingleInput( uint32_t index,
|
||||
uint32_t word );
|
||||
|
||||
/*
|
||||
* HW_PKA_WriteOperand
|
||||
*
|
||||
* Writes one operand of size 'n' 32-bit words into the PKA memory.
|
||||
* This function must not be directly called when using P-256 elliptic curve
|
||||
* dedicated functions.
|
||||
*/
|
||||
extern void HW_PKA_WriteOperand( uint32_t index,
|
||||
int size,
|
||||
const uint32_t* in );
|
||||
|
||||
/*
|
||||
* HW_PKA_Start
|
||||
*
|
||||
* Starts the PKA operation with mode defined by the parameter "mode".
|
||||
* This function must not be directly called when using P-256 elliptic curve
|
||||
* dedicated functions.
|
||||
*
|
||||
* "mode" can be one of the LL_PKA_MODE... definitions that can be found
|
||||
* in "stm32wbxx_ll_pka.h" file.
|
||||
*/
|
||||
extern void HW_PKA_Start( uint32_t mode );
|
||||
|
||||
/*
|
||||
* HW_PKA_EndOfOperation
|
||||
*
|
||||
* Returns 0 if the PKA processing is still active.
|
||||
* Returns a value different from 0 when the PKA processing is complete.
|
||||
*/
|
||||
extern int HW_PKA_EndOfOperation( void );
|
||||
|
||||
/*
|
||||
* HW_PKA_ReadSingleOutput
|
||||
*
|
||||
* Reads one 32-bit word result from the PKA memory.
|
||||
* This function must not be directly called when using P-256 elliptic curve
|
||||
* dedicated functions.
|
||||
*/
|
||||
extern uint32_t HW_PKA_ReadSingleOutput( uint32_t index );
|
||||
|
||||
/*
|
||||
* HW_PKA_ReadResult
|
||||
*
|
||||
* Reads one multi-word result ("size" x 32-bit words) from the PKA memory.
|
||||
* This function must not be directly called when using P-256 elliptic curve
|
||||
* dedicated functions.
|
||||
*/
|
||||
extern void HW_PKA_ReadResult( uint32_t index,
|
||||
int size,
|
||||
uint32_t* out );
|
||||
|
||||
/*
|
||||
* HW_PKA_Disable
|
||||
*
|
||||
* Disables the PKA hardware block.
|
||||
* This function disables also the PKA clock and the PKA security.
|
||||
* It then releases the PKA semaphore.
|
||||
*/
|
||||
extern void HW_PKA_Disable( void );
|
||||
|
||||
/*
|
||||
* Notes:
|
||||
*
|
||||
* - this driver uses a semaphore to handle access to the PKA. The index of
|
||||
* the semaphore must be configured with CFG_HW_PKA_SEMID.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* PKA_P256
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* HW_PKA_P256_StartRangeCheck
|
||||
*
|
||||
* Starts the range check of a point coordinate for P-256 elliptic curve.
|
||||
*
|
||||
* This function sets the parameters in PKA memory and then starts the
|
||||
* processing. The PKA has to be enabled before with HW_PKA_Enable( ).
|
||||
* The user must poll on the result availability by calling the
|
||||
* HW_PKA_EndOfOperation() function.
|
||||
*
|
||||
* The input parameter is one the point coordinate. It must be a vector of
|
||||
* 8 x 32-bit words (32 bytes).
|
||||
*
|
||||
* The check result is retrieved by calling HW_PKA_P256_IsRangeCheckOk().
|
||||
*/
|
||||
extern void HW_PKA_P256_StartRangeCheck( const uint32_t* coord );
|
||||
|
||||
/*
|
||||
* HW_PKA_P256_IsRangeCheckOk
|
||||
*
|
||||
* Reads the result of P-256 range check. This function must only be called
|
||||
* when HW_PKA_EndOfOperation() returns a non-zero value.
|
||||
*
|
||||
* Returns 0 if the check fails ; 1 otherwise.
|
||||
*/
|
||||
extern uint32_t HW_PKA_P256_IsRangeCheckOk( void );
|
||||
|
||||
/*
|
||||
* HW_PKA_P256_StartPointCheck
|
||||
*
|
||||
* Starts the check of a point for P-256 elliptic curve.
|
||||
*
|
||||
* This function sets the parameters in PKA memory and then starts the
|
||||
* processing. The PKA has to be enabled before with HW_PKA_Enable( ).
|
||||
* The user must poll on the result availability by calling the
|
||||
* HW_PKA_EndOfOperation() function.
|
||||
*
|
||||
* The input parameters are the point coordinates. Each parameter must be a
|
||||
* vector of 8 x 32-bit words (32 bytes).
|
||||
*
|
||||
* The check result is retrieved by calling HW_PKA_P256_IsPointCheckOk().
|
||||
*/
|
||||
extern void HW_PKA_P256_StartPointCheck( const uint32_t* x,
|
||||
const uint32_t* y );
|
||||
|
||||
/*
|
||||
* HW_PKA_P256_IsPointCheckOk
|
||||
*
|
||||
* Reads the result of P-256 point check. This function must only be called
|
||||
* when HW_PKA_EndOfOperation() returns a non-zero value.
|
||||
*
|
||||
* Returns 0 if the check fails ; 1 otherwise.
|
||||
*/
|
||||
extern uint32_t HW_PKA_P256_IsPointCheckOk( void );
|
||||
|
||||
/*
|
||||
* HW_PKA_P256_StartEccScalarMul
|
||||
*
|
||||
* Starts the PKA scalar multiplication using the P-256 elliptic curve.
|
||||
*
|
||||
* This function sets the parameters in PKA memory and then starts the
|
||||
* processing. The PKA has to be enabled before with HW_PKA_Enable( ).
|
||||
* The user must poll on the result availability by calling the
|
||||
* HW_PKA_EndOfOperation() function.
|
||||
*
|
||||
* The input parameter is the starting point P defined by its 2 coordinates
|
||||
* p_x and p_y, and the scalar k. Each parameter must be a vector of 8 x 32-bit
|
||||
* words (32 bytes).
|
||||
*/
|
||||
extern void HW_PKA_P256_StartEccScalarMul( const uint32_t* k,
|
||||
const uint32_t* p_x,
|
||||
const uint32_t* p_y );
|
||||
|
||||
/*
|
||||
* HW_PKA_P256_ReadEccScalarMul
|
||||
*
|
||||
* Reads the result of PKA scalar multiplication using the P-256 elliptic
|
||||
* curve. This function must only be called when HW_PKA_EndOfOperation()
|
||||
* returns a non-zero value.
|
||||
*
|
||||
* This function retrieves the result from PKA memory: coordinates of point P,
|
||||
* p_x and p_y, 8 x 32-bit words each (2 times 32 bytes).
|
||||
* Before returning, it disables the PKA block, releasing the PKA semaphore.
|
||||
*/
|
||||
extern void HW_PKA_P256_ReadEccScalarMul( uint32_t* p_x,
|
||||
uint32_t* p_y );
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* RNG
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* The RNG driver is made to generate the random numbers in background instead
|
||||
* of generating them each time they are needed by the application.
|
||||
* Thus, the function HW_RNG_Process() must be called regularly in background
|
||||
* loop to generate a pool of random numbers. The function HW_RNG_Get() reads
|
||||
* the random numbers from the pool.
|
||||
* The size of the pool must be configured with HW_RNG_POOL_SIZE.
|
||||
*/
|
||||
|
||||
/* Error codes definition for HW_RNG return values */
|
||||
enum
|
||||
{
|
||||
HW_RNG_CLOCK_ERROR = CFG_HW_ERROR_OFFSET + 0x101,
|
||||
HW_RNG_NOISE_ERROR = CFG_HW_ERROR_OFFSET + 0x102,
|
||||
HW_RNG_UFLOW_ERROR = CFG_HW_ERROR_OFFSET + 0x103,
|
||||
};
|
||||
|
||||
/* RNG pool size */
|
||||
#define HW_RNG_POOL_SIZE (CFG_HW_RNG_POOL_SIZE)
|
||||
/* Default threshold to refill RNG pool */
|
||||
#define HW_RNG_POOL_DEFAULT_THRESHOLD (12)
|
||||
|
||||
extern int RNG_MutexTake(void);
|
||||
extern int RNG_MutexRelease(void);
|
||||
|
||||
/* RNG_KERNEL_CLK_ON
|
||||
*
|
||||
* Enable RNG kernel clock.
|
||||
*/
|
||||
void RNG_KERNEL_CLK_ON(void);
|
||||
|
||||
/* RNG_KERNEL_CLK_OFF
|
||||
*
|
||||
* Called when RNG kernel clock may be disabled.
|
||||
* Weak function to be implemented by user.
|
||||
*/
|
||||
void RNG_KERNEL_CLK_OFF(void);
|
||||
|
||||
/* HW_RNG_Disable
|
||||
*
|
||||
* Disables the RNG peripheral and switch off its clock in RCC.
|
||||
*/
|
||||
extern void HW_RNG_Disable( void );
|
||||
|
||||
/* HW_RNG_Start
|
||||
*
|
||||
* Starts the generation of random numbers using the RNG IP. This function has
|
||||
* to be called only once at reset before calling HW_RNG_Get() to retrieve
|
||||
* the generated random values.
|
||||
*/
|
||||
extern void HW_RNG_Start( void );
|
||||
|
||||
/*
|
||||
* HW_RNG_Get
|
||||
*
|
||||
* Retrieves "n" random 32-bit words.
|
||||
* "n" must be in the range [1, CFG_HW_RNG_POOL_SIZE].
|
||||
* The random numbers are written in memory from "val" pointer.
|
||||
* "val" must point to a sufficient memory buffer allocated by the caller.
|
||||
*/
|
||||
extern void HW_RNG_Get( uint8_t n,
|
||||
uint32_t* val );
|
||||
|
||||
/*
|
||||
* HW_RNG_Process
|
||||
*
|
||||
* This function must be called in a separate task or in "background" loop.
|
||||
* It implements a simple state machine that enables the RNG block,
|
||||
* generates random numbers and then disables the RNG.
|
||||
* It returns 0 (HW_OK) if the low power mode can be entered.
|
||||
* It returns HW_BUSY as long as this function must be called.
|
||||
* In error conditions, it returns one of the following error codes:
|
||||
* - HW_RNG_CLOCK_ERROR for clock error,
|
||||
* - HW_RNG_NOISE_ERROR for noise source error;
|
||||
* the hardware must then be reset.
|
||||
* - HW_RNG_UFLOW_ERROR in case of pool underflow error.
|
||||
*/
|
||||
extern int HW_RNG_Process( void );
|
||||
|
||||
/*
|
||||
* HW_RNG_EnableClock
|
||||
*
|
||||
* This function enables the RNG clock for "other user" than RNG driver itself
|
||||
*/
|
||||
extern void HW_RNG_EnableClock( uint8_t user_mask );
|
||||
|
||||
/*
|
||||
* HW_RNG_DisableClock
|
||||
*
|
||||
* This function disables the RNG clock for "other user" than RNG driver itself
|
||||
*/
|
||||
extern void HW_RNG_DisableClock( uint8_t user_mask );
|
||||
|
||||
extern void HWCB_RNG_Process( void );
|
||||
|
||||
/*
|
||||
* HW_RNG_Init
|
||||
*
|
||||
* This function initializes RNG (clock, configuration ...)
|
||||
*/
|
||||
extern void HW_RNG_Init(void);
|
||||
|
||||
/*
|
||||
* HW_RNG_Init
|
||||
*
|
||||
* Sets RNG pool threshold (for refill)
|
||||
*/
|
||||
extern void HW_RNG_SetPoolThreshold(uint8_t threshold);
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* GPIO
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Index definitions used for all GPIO functions */
|
||||
enum
|
||||
{
|
||||
HW_GPIO_DBG = 0,
|
||||
HW_GPIO_GREEN_LED = 13,
|
||||
HW_GPIO_RED_LED = 14,
|
||||
HW_GPIO_BLUE_LED = 15,
|
||||
};
|
||||
|
||||
/*
|
||||
* HW_GPIO_Init
|
||||
*
|
||||
* This function initilaizes the GPIO pins used for debug.
|
||||
*/
|
||||
extern void HW_GPIO_Init( const uint32_t* dbg_pins );
|
||||
|
||||
/*
|
||||
* HW_GPIO_Read
|
||||
*
|
||||
* This function reads the output pin which index is given in parameter.
|
||||
* It returns 0 if the pin is low, 1 if the pin is high.
|
||||
*/
|
||||
extern uint8_t HW_GPIO_Read( uint8_t index );
|
||||
|
||||
/*
|
||||
* HW_GPIO_Set
|
||||
*
|
||||
* This function sets to high level the output pin which index is given
|
||||
* in parameter.
|
||||
*/
|
||||
extern void HW_GPIO_Set( uint8_t index );
|
||||
|
||||
/*
|
||||
* HW_GPIO_Reset
|
||||
*
|
||||
* This function resets to low level the output pin which index is given
|
||||
* in parameter.
|
||||
*/
|
||||
extern void HW_GPIO_Reset( uint8_t index );
|
||||
|
||||
extern void GPIO_SetDebug( int gpio_pin,
|
||||
int pin_value );
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* OTP
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef __PACKED_STRUCT
|
||||
{
|
||||
uint8_t additional_data[8]; /*!< 64 bits of data to fill OTP slot */
|
||||
uint8_t bd_address[6]; /*!< Bluetooth Device Address*/
|
||||
uint8_t hsetune; /*!< Load capacitance to be applied on HSE pad */
|
||||
uint8_t index; /*!< Structure index */
|
||||
} HW_OTP_data_t;
|
||||
|
||||
/*
|
||||
* HW_OTP_Read
|
||||
*
|
||||
* Read the OTP
|
||||
*
|
||||
*/
|
||||
int HW_OTP_Read( uint8_t index,
|
||||
HW_OTP_data_t** data );
|
||||
|
||||
/*
|
||||
* HW_OTP_Write
|
||||
*
|
||||
* ReadWrite the OTP
|
||||
*
|
||||
*/
|
||||
int HW_OTP_Write( uint8_t* additional_data,
|
||||
uint8_t* bd_address,
|
||||
uint8_t hsetune,
|
||||
uint8_t index );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HW_H__ */
|
||||
@@ -0,0 +1,332 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_aes.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the AES driver for STM32WBA
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "app_common.h"
|
||||
#include "stm32wbaxx_ll_bus.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void Error_Handler(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define HW_AESX AES
|
||||
|
||||
#define HW_AES_CLOCK_ENABLE( ) LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_AES )
|
||||
#define HW_AES_CLOCK_DISABLE( ) LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_AES )
|
||||
|
||||
#define HW_AES_CLOCK_IS_ENABLE( ) LL_AHB2_GRP1_IsEnabledClock( LL_AHB2_GRP1_PERIPH_AES )
|
||||
|
||||
#define AES_BLOCK_SIZE_WORD (4U)
|
||||
#define AES_BLOCK_SIZE_BYTE (16U)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t run;
|
||||
} HW_AES_VAR_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static HW_AES_VAR_T HW_AES_var;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
__WEAK int CRYP_MutexTake(void)
|
||||
{
|
||||
return 0; /* This shall be implemented by user */
|
||||
}
|
||||
|
||||
__WEAK int CRYP_MutexRelease(void)
|
||||
{
|
||||
return 0; /* This shall be implemented by user */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int HW_AES_Enable( void )
|
||||
{
|
||||
HW_AES_VAR_T* av = &HW_AES_var;
|
||||
|
||||
if (0 != CRYP_MutexTake())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test if the driver is not already in use */
|
||||
if ( HW_AES_CLOCK_IS_ENABLE() )
|
||||
{
|
||||
if (0 != CRYP_MutexRelease())
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
av->run = TRUE;
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
/* Enable AES clock */
|
||||
HW_AES_CLOCK_ENABLE( );
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_SetKey( uint32_t mode,
|
||||
const uint8_t* key )
|
||||
{
|
||||
uint32_t tmp[4];
|
||||
|
||||
/* Retrieve all bytes of key */
|
||||
memcpy( tmp, key, 16 );
|
||||
|
||||
/* Initialize the AES peripheral with default values:
|
||||
- Processing: disabled
|
||||
- Data type: 32-bit
|
||||
- Operating mode: encryption
|
||||
- Chaining mode: ECB
|
||||
- Key size: 128-bit
|
||||
*/
|
||||
HW_AESX->CR = 0;
|
||||
|
||||
/* Copy key bytes to the AES registers */
|
||||
|
||||
if ( mode & HW_AES_REV )
|
||||
{
|
||||
HW_AESX->KEYR0 = tmp[0];
|
||||
HW_AESX->KEYR1 = tmp[1];
|
||||
HW_AESX->KEYR2 = tmp[2];
|
||||
HW_AESX->KEYR3 = tmp[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
HW_AESX->KEYR3 = __REV( tmp[0] );
|
||||
HW_AESX->KEYR2 = __REV( tmp[1] );
|
||||
HW_AESX->KEYR1 = __REV( tmp[2] );
|
||||
HW_AESX->KEYR0 = __REV( tmp[3] );
|
||||
}
|
||||
|
||||
if ( !(mode & HW_AES_ENC) )
|
||||
{
|
||||
/* Set key preparation mode */
|
||||
HW_AESX->CR = AES_CR_MODE_0;
|
||||
|
||||
/* Enable AES processing */
|
||||
HW_AESX->CR |= AES_CR_EN;
|
||||
|
||||
/* Wait for CCF flag to be raised */
|
||||
while ( ! (HW_AESX->ISR & AES_ISR_CCF) );
|
||||
|
||||
/* Clear CCF Flag */
|
||||
HW_AESX->ICR |= AES_ICR_CCF;
|
||||
|
||||
/* Set decryption mode */
|
||||
HW_AESX->CR = AES_CR_MODE_1;
|
||||
}
|
||||
|
||||
/* Enable byte swapping if needed */
|
||||
if ( mode & HW_AES_SWAP )
|
||||
HW_AESX->CR |= AES_CR_DATATYPE_1;
|
||||
|
||||
/* Wait until KEYVALID is set */
|
||||
while ( !(HW_AESX->SR & AES_SR_KEYVALID) );
|
||||
|
||||
/* Enable AES processing */
|
||||
HW_AESX->CR |= AES_CR_EN;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_Crypt( const uint32_t* input,
|
||||
uint32_t* output )
|
||||
{
|
||||
/* Write the input block into the input FIFO */
|
||||
HW_AESX->DINR = input[0];
|
||||
HW_AESX->DINR = input[1];
|
||||
HW_AESX->DINR = input[2];
|
||||
HW_AESX->DINR = input[3];
|
||||
|
||||
/* Wait for CCF flag to be raised */
|
||||
while ( !(HW_AESX->ISR & AES_ISR_CCF) );
|
||||
|
||||
/* Read the output block from the output FIFO */
|
||||
output[0] = HW_AESX->DOUTR;
|
||||
output[1] = HW_AESX->DOUTR;
|
||||
output[2] = HW_AESX->DOUTR;
|
||||
output[3] = HW_AESX->DOUTR;
|
||||
|
||||
/* Clear CCF Flag */
|
||||
HW_AESX->ICR |= AES_ICR_CCF;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_Disable( void )
|
||||
{
|
||||
HW_AES_VAR_T* av = &HW_AES_var;
|
||||
|
||||
if ( av->run )
|
||||
{
|
||||
/* Disable AES processing */
|
||||
HW_AESX->CR = 0;
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
/* Disable AES clock */
|
||||
HW_AES_CLOCK_DISABLE( );
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
if (0 != CRYP_MutexRelease())
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
av->run = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_Crypt8( const uint8_t * pInput, uint8_t * pOutput )
|
||||
{
|
||||
uint32_t pTemp[AES_BLOCK_SIZE_WORD];
|
||||
|
||||
// Transfer 8 -> 32 bits */
|
||||
memcpy( pTemp, pInput, AES_BLOCK_SIZE_BYTE );
|
||||
|
||||
/* Write the input block into the input FIFO */
|
||||
HW_AESX->DINR = __REV( pTemp[0] );
|
||||
HW_AESX->DINR = __REV( pTemp[1] );
|
||||
HW_AESX->DINR = __REV( pTemp[2] );
|
||||
HW_AESX->DINR = __REV( pTemp[3] );
|
||||
|
||||
// -- Wait for CCF flag to be raised /
|
||||
while ( (HW_AESX->ISR & AES_ISR_CCF) == 0x00u )
|
||||
{ }
|
||||
|
||||
/* Read the output block from the output FIFO */
|
||||
pTemp[0] = __REV( HW_AESX->DOUTR );
|
||||
pTemp[1] = __REV( HW_AESX->DOUTR );
|
||||
pTemp[2] = __REV( HW_AESX->DOUTR );
|
||||
pTemp[3] = __REV( HW_AESX->DOUTR );
|
||||
|
||||
/* Transfer 32 -> 8 bits */
|
||||
memcpy( pOutput, pTemp, AES_BLOCK_SIZE_BYTE );
|
||||
|
||||
/* Clear CCF Flag */
|
||||
HW_AESX->ICR |= AES_ICR_CCF;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_InitCcm( uint8_t decrypt,
|
||||
const uint8_t* key,
|
||||
const uint32_t* b0,
|
||||
const uint32_t* b1 )
|
||||
{
|
||||
uint32_t tmp[4], mode = decrypt ? AES_CR_MODE_1 : 0;
|
||||
|
||||
/* CCM init phase */
|
||||
HW_AESX->CR = AES_CR_CHMOD_2 | mode;
|
||||
|
||||
/* Copy key bytes to the AES registers */
|
||||
memcpy( tmp, key, 16 );
|
||||
HW_AESX->KEYR0 = tmp[0];
|
||||
HW_AESX->KEYR1 = tmp[1];
|
||||
HW_AESX->KEYR2 = tmp[2];
|
||||
HW_AESX->KEYR3 = tmp[3];
|
||||
|
||||
/* Copy B0 bytes to the AES registers */
|
||||
HW_AESX->IVR3 = __REV( b0[0] );
|
||||
HW_AESX->IVR2 = __REV( b0[1] );
|
||||
HW_AESX->IVR1 = __REV( b0[2] );
|
||||
HW_AESX->IVR0 = __REV( b0[3] );
|
||||
|
||||
/* Enable AES processing */
|
||||
HW_AESX->CR |= AES_CR_EN;
|
||||
|
||||
/* Wait for CCF flag to be raised */
|
||||
while ( ! (HW_AESX->ISR & AES_ISR_CCF) );
|
||||
|
||||
/* Clear CCF Flag */
|
||||
HW_AESX->ICR |= AES_ICR_CCF;
|
||||
|
||||
/* CCM header phase */
|
||||
HW_AESX->CR = AES_CR_CHMOD_2 | AES_CR_GCMPH_0 | AES_CR_DATATYPE_1;
|
||||
|
||||
/* Enable AES processing */
|
||||
HW_AESX->CR |= AES_CR_EN;
|
||||
|
||||
/* Write the header block B1 into the input FIFO */
|
||||
HW_AESX->DINR = b1[0];
|
||||
HW_AESX->DINR = b1[1];
|
||||
HW_AESX->DINR = b1[2];
|
||||
HW_AESX->DINR = b1[3];
|
||||
|
||||
/* Wait for CCF flag to be raised */
|
||||
while ( !(HW_AESX->ISR & AES_ISR_CCF) );
|
||||
|
||||
/* Clear CCF Flag */
|
||||
HW_AESX->ICR |= AES_ICR_CCF;
|
||||
|
||||
/* CCM payload phase */
|
||||
HW_AESX->CR = (AES_CR_EN | AES_CR_CHMOD_2 |
|
||||
AES_CR_GCMPH_1 | AES_CR_DATATYPE_1 | mode);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_EndCcm( uint8_t tag_length,
|
||||
uint8_t* tag )
|
||||
{
|
||||
uint32_t tmp[4];
|
||||
|
||||
/* CCM final phase */
|
||||
HW_AESX->CR = (AES_CR_EN | AES_CR_CHMOD_2 |
|
||||
AES_CR_GCMPH_0 | AES_CR_GCMPH_1 | AES_CR_DATATYPE_1);
|
||||
|
||||
/* Wait for CCF flag to be raised */
|
||||
while ( !(HW_AESX->ISR & AES_ISR_CCF) );
|
||||
|
||||
/* Read the output block from the output FIFO */
|
||||
tmp[0] = HW_AESX->DOUTR;
|
||||
tmp[1] = HW_AESX->DOUTR;
|
||||
tmp[2] = HW_AESX->DOUTR;
|
||||
tmp[3] = HW_AESX->DOUTR;
|
||||
memcpy( tag, tmp, tag_length );
|
||||
|
||||
/* Clear CCF Flag */
|
||||
HW_AESX->ICR |= AES_ICR_CCF;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_AES_SetLast( uint8_t left_length )
|
||||
{
|
||||
HW_AESX->CR |= (16UL - left_length) << AES_CR_NPBLB_Pos;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief Hardware Interface
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef HW_IF_H
|
||||
#define HW_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32wbaxx.h"
|
||||
#include "stm32wbaxx_hal_conf.h"
|
||||
#include "stm32wbaxx_hal_def.h"
|
||||
#include "stm32wbaxx_ll_exti.h"
|
||||
#include "stm32wbaxx_ll_system.h"
|
||||
#include "stm32wbaxx_ll_rcc.h"
|
||||
#include "stm32wbaxx_ll_bus.h"
|
||||
#include "stm32wbaxx_ll_pwr.h"
|
||||
#include "stm32wbaxx_ll_cortex.h"
|
||||
#include "stm32wbaxx_ll_utils.h"
|
||||
#include "stm32wbaxx_ll_gpio.h"
|
||||
#include "stm32wbaxx_ll_rtc.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*HW_IF_H */
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_otp.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the OTP driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "app_common.h"
|
||||
#include "stm32wbaxx_hal.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int HW_OTP_Read( uint8_t index, HW_OTP_data_t ** otp_ptr )
|
||||
{
|
||||
/* OTP data:
|
||||
* additional_data 8 bytes LSB
|
||||
* bd_address 6 bytes
|
||||
* hsetune 1 byte
|
||||
* index 1 byte MSB
|
||||
*/
|
||||
*otp_ptr = (HW_OTP_data_t*)(FLASH_OTP_BASE + FLASH_OTP_SIZE - 16);
|
||||
|
||||
while ( ( (*otp_ptr)->index != index ) &&
|
||||
( (*otp_ptr) != (HW_OTP_data_t*) FLASH_OTP_BASE ) )
|
||||
{
|
||||
(*otp_ptr) -= 1;
|
||||
}
|
||||
|
||||
if ( (*otp_ptr)->index != index )
|
||||
{
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
return HW_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int HW_OTP_Write( uint8_t* additional_data,
|
||||
uint8_t* bd_address,
|
||||
uint8_t hsetune,
|
||||
uint8_t index )
|
||||
{
|
||||
int err = 1; /* error */
|
||||
HW_OTP_data_t otp;
|
||||
int i;
|
||||
|
||||
/* Fill OTP_Data_s structure */
|
||||
for ( i = 0; i < sizeof(otp.additional_data); i++ )
|
||||
{
|
||||
otp.additional_data[i] = additional_data[i];
|
||||
}
|
||||
|
||||
for ( i = 0; i < sizeof(otp.bd_address); i++ )
|
||||
{
|
||||
otp.bd_address[i] = bd_address[i];
|
||||
}
|
||||
|
||||
otp.hsetune = hsetune;
|
||||
otp.index = index;
|
||||
|
||||
/* Find free space */
|
||||
uint32_t free_address = FLASH_OTP_BASE;
|
||||
while ( ( *(uint64_t*)(free_address) != 0xFFFFFFFFFFFFFFFFUL ) &&
|
||||
( *(uint64_t*)(free_address + 8u) != 0xFFFFFFFFFFFFFFFFUL ) &&
|
||||
( (free_address + 16u) != FLASH_OTP_BASE + FLASH_OTP_SIZE ) )
|
||||
{
|
||||
free_address += 16;
|
||||
}
|
||||
|
||||
if ( ( *(uint64_t*)(free_address) != 0xFFFFFFFFFFFFFFFFUL ) &&
|
||||
( *(uint64_t*)(free_address + 8u) != 0xFFFFFFFFFFFFFFFFUL ) )
|
||||
{
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
/* Store OTP structure in OTP area */
|
||||
|
||||
/* Clear all Flash flags before write operation*/
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
|
||||
|
||||
err = HAL_FLASH_Unlock( );
|
||||
err |= HAL_FLASH_Program( FLASH_NSCR1_PG,
|
||||
free_address, (uint32_t)&otp );
|
||||
err |= HAL_FLASH_Lock( );
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_pka.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the PKA driver for STM32WBA
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "app_common.h"
|
||||
#include "stm32wbaxx_ll_bus.h"
|
||||
#include "stm32wbaxx_ll_pka.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void Error_Handler(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t run;
|
||||
} HW_PKA_VAR_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static HW_PKA_VAR_T HW_PKA_var;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
__WEAK int PKA_MutexTake(void)
|
||||
{
|
||||
return 0; /* This shall be implemented by user */
|
||||
}
|
||||
|
||||
__WEAK int PKA_MutexRelease(void)
|
||||
{
|
||||
return 0; /* This shall be implemented by user */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int HW_PKA_Enable( void )
|
||||
{
|
||||
HW_PKA_VAR_T* pv = &HW_PKA_var;
|
||||
|
||||
/* Test if the driver is not already in use */
|
||||
|
||||
if ( pv->run )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (0 != PKA_MutexTake())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pv->run = TRUE;
|
||||
|
||||
/* Enable the RNG clock as it is needed.
|
||||
* See PKA chapter in IUM: the RNG peripheral must be clocked.
|
||||
*/
|
||||
HW_RNG_EnableClock( 2 );
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
/* Enable the PKA clock */
|
||||
LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_PKA );
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
/* Enable the PKA block */
|
||||
LL_PKA_Enable( PKA );
|
||||
|
||||
/* Wait for PKA initialization OK */
|
||||
while ( !(PKA->SR & PKA_SR_INITOK) );
|
||||
|
||||
/* Reset any pending flag */
|
||||
SET_BIT(PKA->CLRFR, (PKA_CLRFR_PROCENDFC | PKA_CLRFR_RAMERRFC |
|
||||
PKA_CLRFR_ADDRERRFC | PKA_CLRFR_OPERRFC));
|
||||
|
||||
/* Disable the RNG clock as it is no more needed ???
|
||||
*/
|
||||
HW_RNG_DisableClock( 2 );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_WriteSingleInput( uint32_t index, uint32_t word )
|
||||
{
|
||||
/* Write the single word into PKA RAM */
|
||||
|
||||
PKA->RAM[index] = word;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_WriteOperand( uint32_t index, int size, const uint32_t* in )
|
||||
{
|
||||
uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
|
||||
|
||||
/* Write the input data into PKA RAM */
|
||||
|
||||
for ( ; size > 0; size-- )
|
||||
{
|
||||
*pka_ram++ = *in++;
|
||||
}
|
||||
|
||||
/* Write extra zeros into PKA RAM */
|
||||
|
||||
*pka_ram = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_Start( uint32_t mode )
|
||||
{
|
||||
/* Set the configuration */
|
||||
LL_PKA_Config( PKA, mode );
|
||||
|
||||
/* Start the PKA processing */
|
||||
LL_PKA_ClearFlag_PROCEND( PKA );
|
||||
LL_PKA_Start( PKA );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int HW_PKA_EndOfOperation( void )
|
||||
{
|
||||
/* Return 0 if the processing is still active */
|
||||
return LL_PKA_IsActiveFlag_PROCEND( PKA );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32_t HW_PKA_ReadSingleOutput( uint32_t index )
|
||||
{
|
||||
/* Read a single word from PKA RAM */
|
||||
|
||||
return PKA->RAM[index];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_ReadResult( uint32_t index, int size, uint32_t* out )
|
||||
{
|
||||
uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
|
||||
|
||||
/* Read from PKA RAM */
|
||||
|
||||
for ( ; size > 0; size-- )
|
||||
{
|
||||
*out++ = *pka_ram++;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_Disable( void )
|
||||
{
|
||||
HW_PKA_VAR_T* pv = &HW_PKA_var;
|
||||
|
||||
if ( pv->run )
|
||||
{
|
||||
/* Disable the PKA block */
|
||||
LL_PKA_Disable( PKA );
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
/* Disable the PKA clock */
|
||||
LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_PKA );
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
if (0 != PKA_MutexRelease())
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
pv->run = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_pka_p256.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file is an optional part of the PKA driver for STM32WBA.
|
||||
* It is dedicated to the P256 elliptic curve.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "app_common.h"
|
||||
#include "stm32wbaxx_ll_pka.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const uint32_t HW_PKA_P256_gfp[8] =
|
||||
{
|
||||
0xFFFFFFFF, /* LSB */
|
||||
0xFFFFFFFF,
|
||||
0xFFFFFFFF,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000001,
|
||||
0xFFFFFFFF,
|
||||
};
|
||||
|
||||
static const uint32_t HW_PKA_P256_r2[8] =
|
||||
{
|
||||
0x00000002, /* LSB */
|
||||
0x00000005,
|
||||
0x00000003,
|
||||
0xFFFFFFFE,
|
||||
0xFFFFFFF9,
|
||||
0xFFFFFFFB,
|
||||
0xFFFFFFFC,
|
||||
0xFFFFFFFC,
|
||||
};
|
||||
|
||||
static const uint32_t HW_PKA_P256_p_x[8] =
|
||||
{
|
||||
0xD898C296, /* LSB */
|
||||
0xF4A13945,
|
||||
0x2DEB33A0,
|
||||
0x77037D81,
|
||||
0x63A440F2,
|
||||
0xF8BCE6E5,
|
||||
0xE12C4247,
|
||||
0x6B17D1F2,
|
||||
};
|
||||
|
||||
static const uint32_t HW_PKA_P256_p_y[8] =
|
||||
{
|
||||
0x37BF51F5, /* LSB */
|
||||
0xCBB64068,
|
||||
0x6B315ECE,
|
||||
0x2BCE3357,
|
||||
0x7C0F9E16,
|
||||
0x8EE7EB4A,
|
||||
0xFE1A7F9B,
|
||||
0x4FE342E2,
|
||||
};
|
||||
|
||||
static const uint32_t HW_PKA_P256_a[8] =
|
||||
{
|
||||
0x00000003, /* LSB */
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
static const uint32_t HW_PKA_P256_b[8] =
|
||||
{
|
||||
0x27D2604B, /* LSB */
|
||||
0x3BCE3C3E,
|
||||
0xCC53B0F6,
|
||||
0x651D06B0,
|
||||
0x769886BC,
|
||||
0xB3EBBD55,
|
||||
0xAA3A93E7,
|
||||
0x5AC635D8,
|
||||
};
|
||||
|
||||
static const uint32_t HW_PKA_P256_n[8] =
|
||||
{
|
||||
0XFC632551, /* LSB */
|
||||
0XF3B9CAC2,
|
||||
0XA7179E84,
|
||||
0XBCE6FAAD,
|
||||
0XFFFFFFFF,
|
||||
0XFFFFFFFF,
|
||||
0X00000000,
|
||||
0XFFFFFFFF
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_P256_StartRangeCheck( const uint32_t* coord )
|
||||
{
|
||||
/* Set the muber of bits of P */
|
||||
HW_PKA_WriteSingleInput( PKA_COMPARISON_IN_OP_NB_BITS, 256 );
|
||||
|
||||
/* Set the coordinate */
|
||||
HW_PKA_WriteOperand( PKA_COMPARISON_IN_OP1, 8, coord );
|
||||
|
||||
/* Set the modulus value p */
|
||||
HW_PKA_WriteOperand( PKA_COMPARISON_IN_OP2, 8, HW_PKA_P256_gfp );
|
||||
|
||||
/* Start PKA hardware */
|
||||
HW_PKA_Start( LL_PKA_MODE_COMPARISON );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32_t HW_PKA_P256_IsRangeCheckOk( void )
|
||||
{
|
||||
return (HW_PKA_ReadSingleOutput( PKA_COMPARISON_OUT_RESULT ) == 0x916AUL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_P256_StartPointCheck( const uint32_t* x,
|
||||
const uint32_t* y )
|
||||
{
|
||||
/* Set the muber of bits of p */
|
||||
HW_PKA_WriteSingleInput( PKA_POINT_CHECK_IN_MOD_NB_BITS, 256 );
|
||||
|
||||
/* Set the coefficient a sign */
|
||||
HW_PKA_WriteSingleInput( PKA_POINT_CHECK_IN_A_COEFF_SIGN, 1 );
|
||||
|
||||
/* Set the coefficient |a| */
|
||||
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_A_COEFF, 8, HW_PKA_P256_a );
|
||||
|
||||
/* Set the coefficient b */
|
||||
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_B_COEFF, 8, HW_PKA_P256_b );
|
||||
|
||||
/* Set the modulus value p */
|
||||
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_MOD_GF, 8, HW_PKA_P256_gfp );
|
||||
|
||||
/* Set the point coordinate x */
|
||||
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_INITIAL_POINT_X, 8, x );
|
||||
|
||||
/* Set the point coordinate y */
|
||||
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_INITIAL_POINT_Y, 8, y );
|
||||
|
||||
/* Set the Montgomery parameter */
|
||||
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_MONTGOMERY_PARAM,
|
||||
8, HW_PKA_P256_r2 );
|
||||
|
||||
/* Start PKA hardware */
|
||||
HW_PKA_Start( LL_PKA_MODE_POINT_CHECK );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32_t HW_PKA_P256_IsPointCheckOk( void )
|
||||
{
|
||||
return (HW_PKA_ReadSingleOutput( PKA_POINT_CHECK_OUT_ERROR ) == 0xD60DUL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_P256_StartEccScalarMul( const uint32_t* k,
|
||||
const uint32_t* p_x,
|
||||
const uint32_t* p_y )
|
||||
{
|
||||
/* Set the scalar multiplier k length */
|
||||
HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_EXP_NB_BITS, 256 );
|
||||
|
||||
/* Set the modulus length */
|
||||
HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS, 256 );
|
||||
|
||||
/* Set the coefficient a sign */
|
||||
HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_A_COEFF_SIGN, 1 );
|
||||
|
||||
/* Set the coefficient |a| */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_A_COEFF, 8, HW_PKA_P256_a );
|
||||
|
||||
/* Set the coefficient b */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_B_COEFF, 8, HW_PKA_P256_b );
|
||||
|
||||
/* Set the modulus value p */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_MOD_GF, 8, HW_PKA_P256_gfp );
|
||||
|
||||
/* Set the scalar multiplier k */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_K, 8, k );
|
||||
|
||||
/* Set the point P coordinate x */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_X,
|
||||
8, p_x ? p_x : HW_PKA_P256_p_x );
|
||||
|
||||
/* Set the point P coordinate y */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_Y,
|
||||
8, p_y ? p_y : HW_PKA_P256_p_y );
|
||||
|
||||
/* Set the prime order n */
|
||||
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_N_PRIME_ORDER,
|
||||
8, HW_PKA_P256_n );
|
||||
|
||||
/* Start PKA hardware */
|
||||
HW_PKA_Start( LL_PKA_MODE_ECC_MUL );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_PKA_P256_ReadEccScalarMul( uint32_t* p_x,
|
||||
uint32_t* p_y )
|
||||
{
|
||||
/* Read the output point X */
|
||||
if ( p_x )
|
||||
{
|
||||
HW_PKA_ReadResult( PKA_ECC_SCALAR_MUL_OUT_RESULT_X, 8, p_x );
|
||||
}
|
||||
|
||||
/* Read the output point Y as the second half of the result */
|
||||
if ( p_y )
|
||||
{
|
||||
HW_PKA_ReadResult( PKA_ECC_SCALAR_MUL_OUT_RESULT_Y, 8, p_y );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_rng.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the RNG driver for STM32WBA
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "app_common.h"
|
||||
#include "stm32wbaxx_ll_bus.h"
|
||||
#include "stm32wbaxx_ll_rng.h"
|
||||
#include "RTDebug.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern void Error_Handler(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
__WEAK int RNG_MutexTake(void)
|
||||
{
|
||||
return 0; /* This shall be implemented by user */
|
||||
}
|
||||
|
||||
__WEAK int RNG_MutexRelease(void)
|
||||
{
|
||||
return 0; /* This shall be implemented by user */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
__weak void RNG_KERNEL_CLK_ON(void)
|
||||
{
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the RNG_KERNEL_CLK_ON could be implemented in the user file
|
||||
*/
|
||||
LL_RCC_HSI_Enable();
|
||||
while(LL_RCC_HSI_IsReady() == 0)
|
||||
{
|
||||
LL_RCC_HSI_Enable();
|
||||
}
|
||||
}
|
||||
|
||||
__weak void RNG_KERNEL_CLK_OFF(void)
|
||||
{
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the RNG_KERNEL_CLK_OFF could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pool[HW_RNG_POOL_SIZE];
|
||||
uint8_t size;
|
||||
uint8_t run;
|
||||
uint8_t clock_en;
|
||||
int error;
|
||||
} HW_RNG_VAR_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static HW_RNG_VAR_T HW_RNG_var;
|
||||
|
||||
static uint8_t hw_rng_pool_threshold = HW_RNG_POOL_DEFAULT_THRESHOLD;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void HW_RNG_WaitingClockSynchronization( void );
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_RNG_Disable( void )
|
||||
{
|
||||
SYSTEM_DEBUG_SIGNAL_SET(RNG_DISABLE);
|
||||
|
||||
LL_RNG_Disable( RNG );
|
||||
|
||||
/* Disable RNG clocks */
|
||||
HW_RNG_DisableClock( 1 );
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_RESET(RNG_DISABLE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_RNG_EnableClock( uint8_t user_mask )
|
||||
{
|
||||
HW_RNG_VAR_T* pv = &HW_RNG_var;
|
||||
|
||||
RNG_KERNEL_CLK_ON();
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
if ( pv->clock_en == 0 )
|
||||
{
|
||||
LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_RNG );
|
||||
}
|
||||
|
||||
pv->clock_en |= user_mask;
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_RNG_DisableClock( uint8_t user_mask )
|
||||
{
|
||||
HW_RNG_VAR_T* pv = &HW_RNG_var;
|
||||
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
pv->clock_en &= ~user_mask;
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
}
|
||||
|
||||
/* It does not matter much if the temporisation is executed even though
|
||||
* in the meantime pv->clock_en has been updated and is not more equal to 0
|
||||
*/
|
||||
if ( pv->clock_en == 0 )
|
||||
{
|
||||
HW_RNG_WaitingClockSynchronization( );
|
||||
}
|
||||
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
if ( pv->clock_en == 0 )
|
||||
{
|
||||
LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_RNG );
|
||||
}
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
}
|
||||
|
||||
RNG_KERNEL_CLK_OFF();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Wait for 2 RNG kernel clock.
|
||||
* Loop is sized with worst case : RNG kernel clock = 32Khz
|
||||
*/
|
||||
static void HW_RNG_WaitingClockSynchronization( void )
|
||||
{
|
||||
/* RNG busy flag is not available in STM32WBA5xxx */
|
||||
#if defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) || defined(STM32WBA5Mxx)
|
||||
volatile unsigned int cpt;
|
||||
|
||||
for(cpt = 178 ; cpt!=0 ; --cpt);
|
||||
#else
|
||||
/* wait until RNG_SR_BUSY (bit 4) is cleared */
|
||||
while(RNG->SR & (1 << 4));
|
||||
#endif /* defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) || defined(STM32WBA5Mxx) */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* HW_RNG_Run: this function must be called in loop.
|
||||
* It implenments a simple state machine that enables the RNG,
|
||||
* fills the pool with generated random numbers and then disables the RNG.
|
||||
* It always returns 0 in normal conditions. In error conditions, it returns
|
||||
* an error code different from 0.
|
||||
*/
|
||||
static int HW_RNG_Run(HW_RNG_VAR_T* pv)
|
||||
{
|
||||
int i, error = HW_OK;
|
||||
|
||||
/* check for RNG clock error */
|
||||
if (LL_RNG_IsActiveFlag_CECS(RNG))
|
||||
{
|
||||
/* Clear RNG clock error interrupt status flags */
|
||||
LL_RNG_ClearFlag_CEIS(RNG);
|
||||
|
||||
error = HW_RNG_CLOCK_ERROR;
|
||||
}
|
||||
|
||||
/* check for RNG seed error */
|
||||
if (LL_RNG_IsActiveFlag_SEIS(RNG))
|
||||
{
|
||||
/* Clear RNG seed error interrupt status flags */
|
||||
LL_RNG_ClearFlag_SEIS(RNG);
|
||||
|
||||
/* Discard 12 words from RNG_DR in order to clean the pipeline */
|
||||
for ( i = 12; i > 0; i-- )
|
||||
{
|
||||
LL_RNG_ReadRandData32(RNG);
|
||||
}
|
||||
|
||||
error = HW_RNG_NOISE_ERROR;
|
||||
}
|
||||
|
||||
/* if the pool is not full, read the H/W generated values until the pool is full */
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
SYSTEM_DEBUG_SIGNAL_SET(RNG_GEN_RAND_NUM);
|
||||
|
||||
while (pv->size < HW_RNG_POOL_SIZE)
|
||||
{
|
||||
if (LL_RNG_IsActiveFlag_DRDY(RNG))
|
||||
{
|
||||
pv->pool[pv->size] = LL_RNG_ReadRandData32(RNG);
|
||||
pv->size++;
|
||||
}
|
||||
}
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_RESET(RNG_GEN_RAND_NUM);
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
/* pool is full, disable the RNG and its RCC clock */
|
||||
HW_RNG_Disable( );
|
||||
|
||||
/* Reset flag indicating that the RNG is ON */
|
||||
pv->run = FALSE;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_RNG_Start( void )
|
||||
{
|
||||
HW_RNG_VAR_T* pv = &HW_RNG_var;
|
||||
|
||||
/* Reset global variables */
|
||||
pv->size = 0;
|
||||
pv->run = FALSE;
|
||||
pv->error = HW_OK;
|
||||
pv->clock_en = 0;
|
||||
|
||||
if (0 != RNG_MutexTake())
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* Fill the random numbers pool by calling the "run" function */
|
||||
do
|
||||
{
|
||||
pv->error = HW_RNG_Run( pv );
|
||||
}
|
||||
while ( pv->run && !pv->error );
|
||||
|
||||
if (0 != RNG_MutexRelease())
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void HW_RNG_Get( uint8_t n, uint32_t* val )
|
||||
{
|
||||
HW_RNG_VAR_T* pv = &HW_RNG_var;
|
||||
uint32_t pool_value;
|
||||
|
||||
while ( n-- )
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
if ( pv->size == 0 )
|
||||
{
|
||||
pv->error = HW_RNG_UFLOW_ERROR;
|
||||
pool_value = ~pv->pool[HW_RNG_POOL_SIZE - n];
|
||||
}
|
||||
else
|
||||
{
|
||||
pool_value = pv->pool[--pv->size];
|
||||
}
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
*val++ = pool_value;
|
||||
}
|
||||
|
||||
/* Call the process callback function to fill the pool offline */
|
||||
HWCB_RNG_Process( );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int HW_RNG_Process( void )
|
||||
{
|
||||
HW_RNG_VAR_T* pv = &HW_RNG_var;
|
||||
int status = HW_OK;
|
||||
|
||||
if (0 != RNG_MutexTake())
|
||||
{
|
||||
status = HW_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the process is not done or if the pool is not full */
|
||||
if (pv->size < hw_rng_pool_threshold)
|
||||
{
|
||||
HW_RNG_Init();
|
||||
UTILS_ENTER_CRITICAL_SECTION( );
|
||||
|
||||
/* Check if an error occurred during a previous call to HW_RNG API */
|
||||
status = pv->error;
|
||||
pv->error = HW_OK;
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION( );
|
||||
|
||||
if ( status == HW_OK )
|
||||
{
|
||||
/* Call the "run" function that generates random data */
|
||||
status = HW_RNG_Run( pv );
|
||||
|
||||
/* If the process is not done, return "busy" status */
|
||||
if ( (status == HW_OK) && pv->run )
|
||||
{
|
||||
status = HW_BUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != RNG_MutexRelease())
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
if (status != HW_OK)
|
||||
{
|
||||
HWCB_RNG_Process( );
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return status;
|
||||
}
|
||||
|
||||
void HW_RNG_Init(void)
|
||||
{
|
||||
HW_RNG_VAR_T* pv = &HW_RNG_var;
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_SET(RNG_ENABLE);
|
||||
|
||||
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_HSI);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_RNG);
|
||||
LL_RNG_Disable(RNG);
|
||||
while(LL_RNG_IsEnabled(RNG));
|
||||
|
||||
/* Recommended value for NIST compliance, refer to application note AN4230 */
|
||||
/* Using LL macros to set these values is not convenient as it's split
|
||||
in 3 parts and need some bit polling at each step to check completion.
|
||||
So, for efficiency, register direct access */
|
||||
WRITE_REG(RNG->CR, RNG_CR_NIST_VALUE | RNG_CR_CONDRST | RNG_CED_DISABLE);
|
||||
/* Recommended value for NIST compliance, refer to application note AN4230 */
|
||||
|
||||
LL_RNG_DisableClkErrorDetect(RNG);
|
||||
LL_RNG_DisableCondReset(RNG);
|
||||
|
||||
#if !(defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) || defined(STM32WBA5Mxx))
|
||||
while((RNG->SR & (1 << 4)));
|
||||
#endif
|
||||
|
||||
while(LL_RNG_IsEnabledCondReset(RNG));
|
||||
|
||||
LL_RNG_SetHealthConfig(RNG,RNG_HTCR_NIST_VALUE);
|
||||
|
||||
LL_RNG_Enable(RNG);
|
||||
while(!LL_RNG_IsActiveFlag_DRDY(RNG)); /*wait for data to be ready*/
|
||||
|
||||
pv->run = TRUE;
|
||||
SYSTEM_DEBUG_SIGNAL_RESET(RNG_ENABLE);
|
||||
}
|
||||
|
||||
|
||||
void HW_RNG_SetPoolThreshold(uint8_t threshold)
|
||||
{
|
||||
if(threshold < HW_RNG_POOL_SIZE)
|
||||
{
|
||||
hw_rng_pool_threshold = threshold;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file timer_if.c
|
||||
* @author MCD Application Team
|
||||
* @brief Configure RTC Alarm, Tick and Calendar manager
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <math.h>
|
||||
|
||||
#include "stm32wbaxx_hal.h"
|
||||
#include "stm32wbaxx_hal_conf.h"
|
||||
#include "stm32wbaxx_ll_rtc.h"
|
||||
|
||||
#include "timer_if.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Minimum timeout delay of Alarm in ticks
|
||||
*/
|
||||
#define MIN_ALARM_DELAY 3
|
||||
|
||||
/**
|
||||
* @brief Backup seconds register
|
||||
*/
|
||||
#define RTC_BKP_SECONDS RTC_BKP_DR0
|
||||
|
||||
/**
|
||||
* @brief Backup subseconds register
|
||||
*/
|
||||
#define RTC_BKP_SUBSECONDS RTC_BKP_DR1
|
||||
|
||||
/**
|
||||
* @brief Backup msbticks register
|
||||
*/
|
||||
#define RTC_BKP_MSBTICKS RTC_BKP_DR2
|
||||
|
||||
/* #define RTIF_DEBUG */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Timer driver callbacks handler
|
||||
*/
|
||||
const UTIL_TIMER_Driver_s UTIL_TimerDriver =
|
||||
{
|
||||
TIMER_IF_Init,
|
||||
NULL,
|
||||
|
||||
TIMER_IF_StartTimer,
|
||||
TIMER_IF_StopTimer,
|
||||
|
||||
TIMER_IF_SetTimerContext,
|
||||
TIMER_IF_GetTimerContext,
|
||||
|
||||
TIMER_IF_GetTimerElapsedTime,
|
||||
TIMER_IF_GetTimerValue,
|
||||
TIMER_IF_GetMinimumTimeout,
|
||||
|
||||
TIMER_IF_Convert_ms2Tick,
|
||||
TIMER_IF_Convert_Tick2ms,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SysTime driver callbacks handler
|
||||
*/
|
||||
const UTIL_SYSTIM_Driver_s UTIL_SYSTIMDriver =
|
||||
{
|
||||
TIMER_IF_BkUp_Write_Seconds,
|
||||
TIMER_IF_BkUp_Read_Seconds,
|
||||
TIMER_IF_BkUp_Write_SubSeconds,
|
||||
TIMER_IF_BkUp_Read_SubSeconds,
|
||||
TIMER_IF_GetTime,
|
||||
};
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/**
|
||||
* @brief RTC handle
|
||||
*/
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Indicates if the RTC is already Initialized or not
|
||||
*/
|
||||
static bool RTC_Initialized = 0;
|
||||
|
||||
/**
|
||||
* @brief RtcTimerContext
|
||||
*/
|
||||
static uint32_t RtcTimerContext = 0;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef RTIF_DEBUG
|
||||
#include "sys_app.h" /*for app_log*/
|
||||
/**
|
||||
* @brief Post the RTC log string format to the circular queue for printing in using the polling mode
|
||||
*/
|
||||
#define TIMER_IF_DBG_PRINTF(...) do{ {UTIL_ADV_TRACE_COND_FSend(VLEVEL_ALWAYS, T_REG_OFF, TS_OFF, __VA_ARGS__);} }while(0);
|
||||
#else
|
||||
/**
|
||||
* @brief not used
|
||||
*/
|
||||
#define TIMER_IF_DBG_PRINTF(...)
|
||||
#endif /* RTIF_DEBUG */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/**
|
||||
* @brief Get rtc timer Value in rtc tick
|
||||
* @return val the rtc timer value (upcounting)
|
||||
*/
|
||||
static inline uint32_t GetTimerTicks(void);
|
||||
|
||||
/**
|
||||
* @brief Writes MSBticks to backup register
|
||||
* Absolute RTC time in tick is (MSBticks)<<32 + (32bits binary counter)
|
||||
* @note MSBticks incremented every time the 32bits RTC timer wraps around (~44days)
|
||||
* @param[in] MSBticks
|
||||
* @return none
|
||||
*/
|
||||
static void TIMER_IF_BkUp_Write_MSBticks(uint32_t MSBticks);
|
||||
|
||||
/**
|
||||
* @brief Reads MSBticks from backup register
|
||||
* Absolute RTC time in tick is (MSBticks)<<32 + (32bits binary counter)
|
||||
* @note MSBticks incremented every time the 32bits RTC timer wraps around (~44days)
|
||||
* @retval MSBticks
|
||||
*/
|
||||
static uint32_t TIMER_IF_BkUp_Read_MSBticks(void);
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
|
||||
UTIL_TIMER_Status_t TIMER_IF_Init(void)
|
||||
{
|
||||
UTIL_TIMER_Status_t ret = UTIL_TIMER_OK;
|
||||
|
||||
if (RTC_Initialized == false)
|
||||
{
|
||||
/* Stop Timer */
|
||||
TIMER_IF_StopTimer();
|
||||
|
||||
/* DeActivate the Alarm A enabled by MX during MX_RTC_Init() */
|
||||
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
|
||||
|
||||
/* Enable Direct Read of the calendar registers (not through Shadow) */
|
||||
HAL_RTCEx_EnableBypassShadow(&hrtc);
|
||||
|
||||
/* Initialise MSB ticks */
|
||||
TIMER_IF_BkUp_Write_MSBticks(0);
|
||||
|
||||
TIMER_IF_SetTimerContext();
|
||||
|
||||
RTC_Initialized = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UTIL_TIMER_Status_t TIMER_IF_StartTimer(uint32_t timeout)
|
||||
{
|
||||
UTIL_TIMER_Status_t ret = UTIL_TIMER_OK;
|
||||
|
||||
RTC_AlarmTypeDef sAlarm = {0};
|
||||
|
||||
/* Stop timer if one is already started */
|
||||
TIMER_IF_StopTimer();
|
||||
timeout += RtcTimerContext;
|
||||
|
||||
TIMER_IF_DBG_PRINTF("Start timer: time=%d, alarm=%d\n\r", GetTimerTicks(), timeout);
|
||||
|
||||
/* Starts timer */
|
||||
sAlarm.BinaryAutoClr = RTC_ALARMSUBSECONDBIN_AUTOCLR_NO;
|
||||
sAlarm.AlarmTime.SubSeconds = UINT32_MAX - timeout;
|
||||
sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
|
||||
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDBINMASK_NONE;
|
||||
sAlarm.Alarm = RTC_ALARM_A;
|
||||
|
||||
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
|
||||
{
|
||||
/* Initialization Error */
|
||||
while(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UTIL_TIMER_Status_t TIMER_IF_StopTimer(void)
|
||||
{
|
||||
UTIL_TIMER_Status_t ret = UTIL_TIMER_OK;
|
||||
|
||||
/* Clear RTC Alarm Flag */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(&hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Disable the Alarm A interrupt */
|
||||
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_SetTimerContext(void)
|
||||
{
|
||||
/* Store time context */
|
||||
RtcTimerContext = GetTimerTicks();
|
||||
|
||||
TIMER_IF_DBG_PRINTF("TIMER_IF_SetTimerContext=%d\n\r", RtcTimerContext);
|
||||
|
||||
/* Return time context */
|
||||
return RtcTimerContext;
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_GetTimerContext(void)
|
||||
{
|
||||
TIMER_IF_DBG_PRINTF("TIMER_IF_GetTimerContext=%d\n\r", RtcTimerContext);
|
||||
|
||||
/* Return time context */
|
||||
return RtcTimerContext;
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_GetTimerElapsedTime(void)
|
||||
{
|
||||
return ((uint32_t)(GetTimerTicks() - RtcTimerContext));
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_GetTimerValue(void)
|
||||
{
|
||||
if (RTC_Initialized == true)
|
||||
{
|
||||
return GetTimerTicks();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_GetMinimumTimeout(void)
|
||||
{
|
||||
return (MIN_ALARM_DELAY);
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_Convert_ms2Tick(uint32_t timeMilliSec)
|
||||
{
|
||||
return ((uint32_t)( ( ( (uint64_t) timeMilliSec ) << RTC_N_PREDIV_S ) / 1000U ) );
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_Convert_Tick2ms(uint32_t tick)
|
||||
{
|
||||
return ((uint32_t)( ( ( ( int64_t)( tick ) ) * 1000U ) >> RTC_N_PREDIV_S ) );
|
||||
}
|
||||
|
||||
void TIMER_IF_DelayMs(uint32_t delay)
|
||||
{
|
||||
uint32_t delayTicks = TIMER_IF_Convert_ms2Tick(delay);
|
||||
uint32_t timeout = GetTimerTicks();
|
||||
|
||||
/* Wait delay ms */
|
||||
while (((GetTimerTicks() - timeout)) < delayTicks)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
UTIL_TIMER_IRQ_Handler();
|
||||
}
|
||||
|
||||
void HAL_RTCEx_SSRUEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Called every 48 days with 1024 ticks per seconds */
|
||||
TIMER_IF_DBG_PRINTF(">>Handler SSRUnderflow at %d\n\r", GetTimerTicks());
|
||||
|
||||
/* Increment MSBticks */
|
||||
uint32_t MSB_ticks = TIMER_IF_BkUp_Read_MSBticks();
|
||||
TIMER_IF_BkUp_Write_MSBticks(MSB_ticks + 1);
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_GetTime(uint16_t *mSeconds)
|
||||
{
|
||||
uint64_t ticks;
|
||||
uint32_t timerValueLsb = GetTimerTicks();
|
||||
uint32_t timerValueMSB = TIMER_IF_BkUp_Read_MSBticks();
|
||||
|
||||
ticks = (((uint64_t) timerValueMSB) << 32) + timerValueLsb;
|
||||
|
||||
uint32_t seconds = (uint32_t)(ticks >> RTC_N_PREDIV_S);
|
||||
|
||||
ticks = (uint32_t) ticks & RTC_PREDIV_S;
|
||||
|
||||
*mSeconds = TIMER_IF_Convert_Tick2ms(ticks);
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
void TIMER_IF_BkUp_Write_Seconds(uint32_t Seconds)
|
||||
{
|
||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_SECONDS, Seconds);
|
||||
}
|
||||
|
||||
void TIMER_IF_BkUp_Write_SubSeconds(uint32_t SubSeconds)
|
||||
{
|
||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_SUBSECONDS, SubSeconds);
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_BkUp_Read_Seconds(void)
|
||||
{
|
||||
return HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_SECONDS);
|
||||
}
|
||||
|
||||
uint32_t TIMER_IF_BkUp_Read_SubSeconds(void)
|
||||
{
|
||||
return HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_SUBSECONDS);
|
||||
}
|
||||
|
||||
static void TIMER_IF_BkUp_Write_MSBticks(uint32_t MSBticks)
|
||||
{
|
||||
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_MSBTICKS, MSBticks);
|
||||
}
|
||||
|
||||
static uint32_t TIMER_IF_BkUp_Read_MSBticks(void)
|
||||
{
|
||||
uint32_t MSBticks;
|
||||
MSBticks = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_MSBTICKS);
|
||||
return MSBticks;
|
||||
}
|
||||
|
||||
static inline uint32_t GetTimerTicks(void)
|
||||
{
|
||||
uint32_t ssr = LL_RTC_TIME_GetSubSecond(RTC);
|
||||
/* read twice to make sure value it valid*/
|
||||
while (ssr != LL_RTC_TIME_GetSubSecond(RTC))
|
||||
{
|
||||
ssr = LL_RTC_TIME_GetSubSecond(RTC);
|
||||
}
|
||||
return UINT32_MAX - ssr;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file timer_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief configuration of the timer_if.c instances
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef TIMER_IF_H
|
||||
#define TIMER_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32_timer.h"
|
||||
#include "stm32_systime.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define RTC_N_PREDIV_S (10U)
|
||||
#define RTC_PREDIV_S ( ( 1U << RTC_N_PREDIV_S ) - 1U )
|
||||
#define RTC_PREDIV_A ( ( 1U << ( 15U - RTC_N_PREDIV_S ) ) - 1U )
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
/**
|
||||
* @brief Init RTC hardware
|
||||
* @return Status based on @ref UTIL_TIMER_Status_t
|
||||
*/
|
||||
UTIL_TIMER_Status_t TIMER_IF_Init(void);
|
||||
|
||||
/**
|
||||
* @brief Set the alarm
|
||||
* @note The alarm is set at timeout from timer Reference (TimerContext)
|
||||
* @param timeout Duration of the Timer in ticks
|
||||
* @return Status based on @ref UTIL_TIMER_Status_t
|
||||
*/
|
||||
UTIL_TIMER_Status_t TIMER_IF_StartTimer(uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Stop the Alarm
|
||||
* @return Status based on @ref UTIL_TIMER_Status_t
|
||||
*/
|
||||
UTIL_TIMER_Status_t TIMER_IF_StopTimer(void);
|
||||
|
||||
/**
|
||||
* @brief set timer Reference (TimerContext)
|
||||
* @return Timer Reference Value in Ticks
|
||||
*/
|
||||
uint32_t TIMER_IF_SetTimerContext(void);
|
||||
|
||||
/**
|
||||
* @brief Get the RTC timer Reference
|
||||
* @return Timer Value in Ticks
|
||||
*/
|
||||
uint32_t TIMER_IF_GetTimerContext(void);
|
||||
|
||||
/**
|
||||
* @brief Get the timer elapsed time since timer Reference (TimerContext) was set
|
||||
* @return RTC Elapsed time in ticks
|
||||
*/
|
||||
uint32_t TIMER_IF_GetTimerElapsedTime(void);
|
||||
|
||||
/**
|
||||
* @brief Get the timer value
|
||||
* @return RTC Timer value in ticks
|
||||
*/
|
||||
uint32_t TIMER_IF_GetTimerValue(void);
|
||||
|
||||
/**
|
||||
* @brief Return the minimum timeout in ticks the RTC is able to handle
|
||||
* @return minimum value for a timeout in ticks
|
||||
*/
|
||||
uint32_t TIMER_IF_GetMinimumTimeout(void);
|
||||
|
||||
/**
|
||||
* @brief a delay of delay ms by polling RTC
|
||||
* @param delay in ms
|
||||
*/
|
||||
void TIMER_IF_DelayMs(uint32_t delay);
|
||||
|
||||
/**
|
||||
* @brief converts time in ms to time in ticks
|
||||
* @param[in] timeMilliSec time in milliseconds
|
||||
* @return time in timer ticks
|
||||
*/
|
||||
uint32_t TIMER_IF_Convert_ms2Tick(uint32_t timeMilliSec);
|
||||
|
||||
/**
|
||||
* @brief converts time in ticks to time in ms
|
||||
* @param[in] tick time in timer ticks
|
||||
* @return time in timer milliseconds
|
||||
*/
|
||||
uint32_t TIMER_IF_Convert_Tick2ms(uint32_t tick);
|
||||
|
||||
/**
|
||||
* @brief Get rtc time
|
||||
* @param[out] subSeconds in ticks
|
||||
* @return time seconds
|
||||
*/
|
||||
uint32_t TIMER_IF_GetTime(uint16_t *subSeconds);
|
||||
|
||||
/**
|
||||
* @brief write seconds in backUp register
|
||||
* @note Used to store seconds difference between RTC time and Unix time
|
||||
* @param[in] Seconds time in seconds
|
||||
*/
|
||||
void TIMER_IF_BkUp_Write_Seconds(uint32_t Seconds);
|
||||
|
||||
/**
|
||||
* @brief reads seconds from backUp register
|
||||
* @note Used to store seconds difference between RTC time and Unix time
|
||||
* @return Time in seconds
|
||||
*/
|
||||
uint32_t TIMER_IF_BkUp_Read_Seconds(void);
|
||||
|
||||
/**
|
||||
* @brief writes SubSeconds in backUp register
|
||||
* @note Used to store SubSeconds difference between RTC time and Unix time
|
||||
* @param[in] SubSeconds time in SubSeconds
|
||||
*/
|
||||
void TIMER_IF_BkUp_Write_SubSeconds(uint32_t SubSeconds);
|
||||
|
||||
/**
|
||||
* @brief reads SubSeconds from backUp register
|
||||
* @note Used to store SubSeconds difference between RTC time and Unix time
|
||||
* @return Time in SubSeconds
|
||||
*/
|
||||
uint32_t TIMER_IF_BkUp_Read_SubSeconds(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TIMER_IF_H */
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file baes.h
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the interface of the basic AES software module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef BAES_H__
|
||||
#define BAES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Basic AES module dedicated to BLE stack with the following features:
|
||||
* - AES ECB encryption
|
||||
* - AES CMAC computation
|
||||
*
|
||||
* Configuration: the file "app_common.h" is included in this module.
|
||||
* It must define:
|
||||
* - CFG_BAES_SW equals to 1 for software implementation
|
||||
* - CFG_BAES_SW equals to 0 for use of hardware accelerator
|
||||
*
|
||||
* Notes:
|
||||
* - only 128-bit key is supported
|
||||
* - re-entrance is not supported
|
||||
*/
|
||||
|
||||
/* General interface */
|
||||
|
||||
extern void BAES_Reset( void );
|
||||
|
||||
/* AES ECB interface */
|
||||
|
||||
extern void BAES_EcbCrypt( const uint8_t* key,
|
||||
const uint8_t* input,
|
||||
uint8_t* output,
|
||||
int enc );
|
||||
|
||||
/* AES CMAC interface */
|
||||
|
||||
extern void BAES_CmacSetKey( const uint8_t* key );
|
||||
|
||||
extern void BAES_CmacSetVector( const uint8_t * pIV );
|
||||
|
||||
extern void BAES_CmacCompute( const uint8_t* input,
|
||||
uint32_t size,
|
||||
uint8_t* output );
|
||||
|
||||
/* AES CCM interface */
|
||||
|
||||
extern int BAES_CcmCrypt( uint8_t mode,
|
||||
const uint8_t* key,
|
||||
uint8_t iv_length,
|
||||
const uint8_t* iv,
|
||||
uint16_t add_length,
|
||||
const uint8_t* add,
|
||||
uint16_t input_length,
|
||||
const uint8_t* input,
|
||||
uint8_t tag_length,
|
||||
uint8_t* tag,
|
||||
uint8_t* output );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BAES_H__ */
|
||||
@@ -0,0 +1,120 @@
|
||||
/*****************************************************************************
|
||||
* @file baes_ccm.c
|
||||
*
|
||||
* @brief This file contains the AES CCM implementation.
|
||||
*****************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2018-2024 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.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#include "baes_global.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Byte/word manipulation macro definitions
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Returns the least significant byte from a word */
|
||||
#define BYTE0(w) ((uint8_t)((w) >> 0))
|
||||
|
||||
/* Returns the second least significant byte from a word */
|
||||
#define BYTE1(w) ((uint8_t)((w) >> 8))
|
||||
|
||||
/* Macro to set a 16-bit word into a byte table in big endian */
|
||||
#define SET_U16_BE( b, i, v ) M_BEGIN uint16_t v_ = (uint16_t)(v); \
|
||||
uint8_t *b_ = &((uint8_t*)(b))[i]; \
|
||||
b_[1] = BYTE0(v_); \
|
||||
b_[0] = BYTE1(v_); M_END
|
||||
|
||||
int BAES_CcmCrypt( uint8_t mode,
|
||||
const uint8_t* key,
|
||||
uint8_t iv_length,
|
||||
const uint8_t* iv,
|
||||
uint16_t add_length,
|
||||
const uint8_t* add,
|
||||
uint16_t input_length,
|
||||
const uint8_t* input,
|
||||
uint8_t tag_length,
|
||||
uint8_t* tag,
|
||||
uint8_t* output )
|
||||
{
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
/* This implementation of AES CCM only supports HW AES and it also only
|
||||
* supports the following range for input parameters:
|
||||
* - tag_length: 4..16 (multiple of 2)
|
||||
* - iv_length: 7..13
|
||||
* - add_length: 1..14
|
||||
*/
|
||||
uint32_t left_len, b0[4], bx[4];
|
||||
uint8_t len, *b;
|
||||
|
||||
/* Build B0 */
|
||||
b = (uint8_t*)b0;
|
||||
memset( b0, 0, 16 );
|
||||
b[0] = (1U << 6) | (((tag_length - 2) / 2) << 3) | (14U - iv_length);
|
||||
memcpy( b + 1, iv, iv_length );
|
||||
SET_U16_BE( b, 14, input_length );
|
||||
|
||||
/* Build B1 */
|
||||
b = (uint8_t*)bx;
|
||||
memset( bx, 0, 16 );
|
||||
b[1] = add_length;
|
||||
memcpy( b + 2, add, add_length );
|
||||
|
||||
/* Start CCM process with Init and Header phases */
|
||||
HW_AES_Enable( );
|
||||
HW_AES_InitCcm( mode, key, b0, bx );
|
||||
|
||||
/* Continue CCM process with Payload Phase */
|
||||
left_len = input_length;
|
||||
while ( left_len > 0 )
|
||||
{
|
||||
len = 16;
|
||||
if ( left_len < 16 )
|
||||
{
|
||||
len = (uint8_t)left_len;
|
||||
memset( bx, 0, 16 );
|
||||
|
||||
if ( mode )
|
||||
HW_AES_SetLast( len );
|
||||
}
|
||||
|
||||
memcpy( b, input, len );
|
||||
HW_AES_Crypt( bx, bx );
|
||||
memcpy( output, b, len );
|
||||
input += len;
|
||||
output += len;
|
||||
left_len -= len;
|
||||
}
|
||||
|
||||
/* End CCM process with Final Phase */
|
||||
HW_AES_EndCcm( tag_length, mode ? b : tag );
|
||||
HW_AES_Disable( );
|
||||
|
||||
/* Verification of the tag in case of decryption */
|
||||
if ( mode )
|
||||
{
|
||||
uint8_t diff = 0;
|
||||
for ( int i = 0; i < tag_length; i++ )
|
||||
diff |= tag[i] ^ b[i];
|
||||
|
||||
return (int)diff;
|
||||
}
|
||||
|
||||
#endif /* CFG_BAES_SW == 0 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file baes_cmac.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the AES CMAC implementation.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "baes_global.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t iv[4]; /* Temporary result/IV */
|
||||
|
||||
#if CFG_BAES_SW != 0
|
||||
|
||||
uint32_t exp_key[44]; /* Expanded AES key */
|
||||
|
||||
#endif /* CFG_BAES_SW != 0 */
|
||||
|
||||
} BAES_CMAC_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
BAES_CMAC_t BAES_CMAC_var;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* AES key roll for CMAC Mode
|
||||
*
|
||||
*/
|
||||
|
||||
static void BAES_CmacKeyRoll( uint32_t* key )
|
||||
{
|
||||
uint32_t carry = ((key[0] >> 31) & 1) * 0x87UL;
|
||||
key[0] = (key[0] << 1) | (key[1] >> 31);
|
||||
key[1] = (key[1] << 1) | (key[2] >> 31);
|
||||
key[2] = (key[2] << 1) | (key[3] >> 31);
|
||||
key[3] = (key[3] << 1) ^ carry;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* AES ECB encryption for CMAC Mode
|
||||
*
|
||||
*/
|
||||
|
||||
static void BAES_CmacRawEncrypt( const uint32_t* input,
|
||||
uint32_t* output )
|
||||
{
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
HW_AES_Crypt( input, output );
|
||||
|
||||
#else /* CFG_BAES_SW != 0 */
|
||||
|
||||
BAES_CMAC_t *av = &BAES_CMAC_var;
|
||||
|
||||
BAES_RawEncrypt( input, output, av->exp_key );
|
||||
|
||||
#endif /* CFG_BAES_SW != 0 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Initialization for AES-CMAC for Authentication TAG Generation.
|
||||
* Must be called each time a new CMAC has to be computed.
|
||||
*/
|
||||
|
||||
void BAES_CmacSetKey( const uint8_t* key )
|
||||
{
|
||||
BAES_CMAC_t *av = &BAES_CMAC_var;
|
||||
|
||||
/* Initialize for ECB encoding */
|
||||
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
HW_AES_Enable( );
|
||||
HW_AES_SetKey( HW_AES_ENC, key );
|
||||
|
||||
#else /* CFG_BAES_SW != 0 */
|
||||
|
||||
uint32_t tmp[4];
|
||||
memcpy( tmp, key, 16 );
|
||||
BAES_COPY_REV( av->exp_key, tmp );
|
||||
|
||||
BAES_EncKeySchedule( av->exp_key );
|
||||
|
||||
#endif /* CFG_BAES_SW != 0 */
|
||||
|
||||
/* set IV to zero */
|
||||
av->iv[0] = av->iv[1] = av->iv[2] = av->iv[3] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization for AES-CMAC for Authentication TAG Generation.
|
||||
* Must be called each time a new CMAC has to be computed.
|
||||
*/
|
||||
|
||||
void BAES_CmacSetVector( const uint8_t * pIV )
|
||||
{
|
||||
BAES_CMAC_t * av = &BAES_CMAC_var;
|
||||
|
||||
// -- Update IV if exist else set to zero --
|
||||
if ( pIV != NULL )
|
||||
{ memcpy( av->iv, pIV, AES_BLOCK_SIZE_BYTE ); }
|
||||
else
|
||||
{ memset( av->iv, 0x00, AES_BLOCK_SIZE_BYTE ); }
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* AES Encryption in CMAC Mode
|
||||
*
|
||||
* This function can be called multiple times with "size" multiple of 16 and
|
||||
* "output" parameter set to NULL. However, in the last call to this function,
|
||||
* any positive value for "size" is allowed and the "output" parameter must not
|
||||
* be NULL.
|
||||
*/
|
||||
|
||||
void BAES_CmacCompute( const uint8_t* input,
|
||||
uint32_t size,
|
||||
uint8_t* output )
|
||||
{
|
||||
BAES_CMAC_t *av = &BAES_CMAC_var;
|
||||
uint32_t i;
|
||||
uint32_t last_size = 0;
|
||||
uint32_t tmp[4], key[4];
|
||||
const uint8_t* ptr = input;
|
||||
|
||||
if ( output )
|
||||
{
|
||||
/* In case of final append, compute size of last block */
|
||||
last_size = size % 16;
|
||||
if ( (size != 0) && (last_size == 0) )
|
||||
last_size = 16;
|
||||
size -= last_size;
|
||||
}
|
||||
|
||||
while ( size )
|
||||
{
|
||||
/* Load the input of all blocks but the last one
|
||||
and xor data with previous tag */
|
||||
memcpy( tmp, ptr, 16 );
|
||||
BAES_REV_XOR( tmp, av->iv );
|
||||
|
||||
/* Encrypt block */
|
||||
BAES_CmacRawEncrypt( tmp, av->iv );
|
||||
|
||||
/* Next block */
|
||||
ptr += 16;
|
||||
size -= 16;
|
||||
}
|
||||
|
||||
if ( output )
|
||||
{
|
||||
/* Load the input bytes left with 0 padding */
|
||||
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
|
||||
for ( i = 0; i < last_size; i++ )
|
||||
{
|
||||
BAES_OR_BYTE_BE( tmp, i, ptr[i] );
|
||||
}
|
||||
|
||||
/* Compute K1 */
|
||||
key[0] = key[1] = key[2] = key[3] = 0;
|
||||
BAES_CmacRawEncrypt( key, key );
|
||||
BAES_CmacKeyRoll( key );
|
||||
|
||||
/* Add padding and compute K2 if the last block is not full */
|
||||
if ( last_size < 16 )
|
||||
{
|
||||
BAES_OR_BYTE_BE( tmp, last_size, 0x80 );
|
||||
BAES_CmacKeyRoll( key );
|
||||
}
|
||||
|
||||
/* Xor data with previous tag and key */
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
tmp[i] ^= av->iv[i] ^ key[i];
|
||||
}
|
||||
|
||||
/* Encrypt block */
|
||||
BAES_CmacRawEncrypt( tmp, av->iv );
|
||||
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
HW_AES_Disable( );
|
||||
|
||||
#endif /* CFG_BAES_SW == 0 */
|
||||
|
||||
/* Write the tag */
|
||||
BAES_COPY_REV( tmp, av->iv );
|
||||
memcpy( output, tmp, 16 );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file baes_ecb.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the AES ECB functions implementation.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "baes_global.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void BAES_Reset( void )
|
||||
{
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
HW_AES_Disable( );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void BAES_EcbCrypt( const uint8_t* key,
|
||||
const uint8_t* input,
|
||||
uint8_t* output,
|
||||
int enc )
|
||||
{
|
||||
uint32_t tmp[4];
|
||||
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
HW_AES_Enable( );
|
||||
HW_AES_SetKey( (enc ? (HW_AES_ENC | HW_AES_REV) : (HW_AES_DEC | HW_AES_REV)),
|
||||
key );
|
||||
|
||||
#else /* CFG_BAES_SW != 0 */
|
||||
|
||||
uint32_t exp_key[44];
|
||||
|
||||
/* Retrieve all bytes from key */
|
||||
memcpy( exp_key, key, 16 );
|
||||
BAES_SWAP( exp_key );
|
||||
|
||||
#if CFG_BAES_SW_DECRYPTION != 0
|
||||
if ( !enc )
|
||||
BAES_DecKeySchedule( exp_key );
|
||||
else
|
||||
#endif /* CFG_BAES_SW_DECRYPTION != 0 */
|
||||
BAES_EncKeySchedule( exp_key );
|
||||
|
||||
#endif /* CFG_BAES_SW != 0 */
|
||||
|
||||
/* Retrieve all bytes from input */
|
||||
memcpy( tmp, input, 16 );
|
||||
BAES_SWAP( tmp );
|
||||
|
||||
#if CFG_BAES_SW == 0
|
||||
|
||||
HW_AES_Crypt( tmp, tmp );
|
||||
HW_AES_Disable( );
|
||||
|
||||
#else /* CFG_BAES_SW != 0 */
|
||||
|
||||
#if CFG_BAES_SW_DECRYPTION != 0
|
||||
if ( !enc )
|
||||
BAES_RawDecrypt( tmp, tmp, exp_key );
|
||||
else
|
||||
#endif /* CFG_BAES_SW_DECRYPTION != 0 */
|
||||
BAES_RawEncrypt( tmp, tmp, exp_key );
|
||||
|
||||
#endif /* CFG_BAES_SW != 0 */
|
||||
|
||||
/* Write all bytes to output */
|
||||
BAES_SWAP( tmp );
|
||||
memcpy( output, tmp, 16 );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file baes_global.h
|
||||
* @author MCD Application Team
|
||||
* @brief This file contains the internal definitions of the AES software
|
||||
* module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef BAES_GLOBAL_H__
|
||||
#define BAES_GLOBAL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "app_common.h"
|
||||
#include "baes.h"
|
||||
|
||||
/* Default software configuration */
|
||||
#define AES_BLOCK_SIZE_BIT 128u /* AES Size in Bits */
|
||||
#define AES_BLOCK_SIZE_BYTE 16u /* AES Size in Bytes */
|
||||
#define AES_BLOCK_SIZE_WORD 4u /* AES Size in Words */
|
||||
|
||||
#define AES_EXPANDED_KEY_SIZE 44u
|
||||
|
||||
/* By default, use of AES H/W implementation instead of S/W */
|
||||
#ifndef CFG_BAES_SW
|
||||
#define CFG_BAES_SW 0
|
||||
#endif
|
||||
|
||||
#if CFG_BAES_SW == 1
|
||||
|
||||
/* Enables to include AES S/W decryption when set to 1 */
|
||||
#ifndef CFG_BAES_SW_DECRYPTION
|
||||
#define CFG_BAES_SW_DECRYPTION 0
|
||||
#endif
|
||||
|
||||
/* Choice of the AES S/W algorithm version:
|
||||
* 1: slow version with 522 bytes of look-up tables
|
||||
* 2: fast version with 2048 bytes of look-up tables */
|
||||
#ifndef CFG_BAES_SW_ALGORITHM
|
||||
#define CFG_BAES_SW_ALGORITHM 1
|
||||
#endif
|
||||
|
||||
#endif /* CFG_BAES_SW == 1 */
|
||||
|
||||
/* Internal macros */
|
||||
|
||||
/* Reverse the words in a 4-word array */
|
||||
#define BAES_SWAP( w ) \
|
||||
M_BEGIN uint32_t t_; \
|
||||
t_ = (w)[0]; (w)[0] = (w)[3]; (w)[3] = t_; \
|
||||
t_ = (w)[1]; (w)[1] = (w)[2]; (w)[2] = t_; \
|
||||
M_END
|
||||
|
||||
/* Reverse the bytes and words in a 4-word array */
|
||||
#define BAES_SWAP_REV( w ) \
|
||||
M_BEGIN uint32_t t_; \
|
||||
t_ = (w)[0]; (w)[0] = __REV((w)[3]); (w)[3] = __REV(t_); \
|
||||
t_ = (w)[1]; (w)[1] = __REV((w)[2]); (w)[2] = __REV(t_); \
|
||||
M_END
|
||||
|
||||
/* Reverse the words of a 4-word array and xor the result */
|
||||
#define BAES_SWAP_XOR( w, x ) \
|
||||
M_BEGIN uint32_t t_; \
|
||||
t_ = (w)[0]; (w)[0] = (w)[3] ^ ((x)[0]); (w)[3] = t_ ^ ((x)[3]); \
|
||||
t_ = (w)[1]; (w)[1] = (w)[2] ^ ((x)[1]); (w)[2] = t_ ^ ((x)[2]); \
|
||||
M_END
|
||||
|
||||
/* Reverse the bytes of a 4-word array and xor the result */
|
||||
#define BAES_REV_XOR( w, x ) \
|
||||
M_BEGIN \
|
||||
(w)[0] = __REV((w)[0]) ^ ((x)[0]); (w)[1] = __REV((w)[1]) ^ ((x)[1]); \
|
||||
(w)[2] = __REV((w)[2]) ^ ((x)[2]); (w)[3] = __REV((w)[3]) ^ ((x)[3]); \
|
||||
M_END
|
||||
|
||||
/* Copy and reverse the words of a 4-word array */
|
||||
#define BAES_COPY_SWAP( d, s ) \
|
||||
M_BEGIN \
|
||||
(d)[0] = (s)[3]; (d)[1] = (s)[2]; \
|
||||
(d)[2] = (s)[1]; (d)[3] = (s)[0]; \
|
||||
M_END
|
||||
|
||||
/* Copy and reverse the bytes of a 4-word array */
|
||||
#define BAES_COPY_REV( d, s ) \
|
||||
M_BEGIN \
|
||||
(d)[0] = __REV((s)[0]); (d)[1] = __REV((s)[1]); \
|
||||
(d)[2] = __REV((s)[2]); (d)[3] = __REV((s)[3]); \
|
||||
M_END
|
||||
|
||||
/* Modifies a byte in a word array in Big Endian */
|
||||
#define BAES_OR_BYTE_BE( w, n, b ) \
|
||||
(w)[(n)/4] |= ((uint32_t)(b)) << (8 * (3-((n)%4)))
|
||||
|
||||
/* Note: BYTE0, BYTE1, BYTE2, BYTE3 and BTOW macros are also used
|
||||
but they should be defined in "common.h" */
|
||||
|
||||
/* Internal functions */
|
||||
|
||||
extern void BAES_EncKeySchedule( uint32_t* p_exp_key );
|
||||
|
||||
extern void BAES_DecKeySchedule( uint32_t* p_exp_key );
|
||||
|
||||
extern void BAES_RawEncrypt( const uint32_t* p_in,
|
||||
uint32_t* p_out,
|
||||
const uint32_t *p_exp_key );
|
||||
|
||||
extern void BAES_RawDecrypt( const uint32_t* p_in,
|
||||
uint32_t* p_out,
|
||||
const uint32_t* p_exp_key );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BAES_GLOBAL_H__ */
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file flash_driver.c
|
||||
* @author MCD Application Team
|
||||
* @brief The Flash Driver module is the interface layer between Flash
|
||||
* management modules and HAL Flash drivers
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2023 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "flash_driver.h"
|
||||
#include "utilities_conf.h"
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
|
||||
#define FD_CTRL_NO_BIT_SET (0UL) /* value used to reset the Flash Control status */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief variable used to represent the Flash Control status
|
||||
*/
|
||||
static volatile FD_Flash_ctrl_bm_t FD_Flash_Control_status = FD_CTRL_NO_BIT_SET;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Update Flash Control status
|
||||
* @param Flags_bm: Bit mask identifying the caller (1 bit per user)
|
||||
* @param Status: Action requested (enable or disable flash access)
|
||||
* @retval None
|
||||
*/
|
||||
void FD_SetStatus(FD_Flash_ctrl_bm_t Flags_bm, FD_FLASH_Status_t Status)
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
switch (Status)
|
||||
{
|
||||
case LL_FLASH_DISABLE:
|
||||
{
|
||||
FD_Flash_Control_status |= (1u << Flags_bm);
|
||||
break;
|
||||
}
|
||||
case LL_FLASH_ENABLE:
|
||||
{
|
||||
FD_Flash_Control_status &= ~(1u << Flags_bm);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a block of 128 bits (4 32-bit words) in Flash
|
||||
* @param Dest: Address where to write in Flash (128-bit aligned)
|
||||
* @param Payload: Address of data to be written in Flash (32-bit aligned)
|
||||
* @retval FD_FlashOp_Status_t: Success or failure of Flash write operation
|
||||
*/
|
||||
FD_FlashOp_Status_t FD_WriteData(uint32_t Dest, uint32_t Payload)
|
||||
{
|
||||
FD_FlashOp_Status_t status = FD_FLASHOP_FAILURE;
|
||||
|
||||
/* Check if RFTS OR Application allow flash access */
|
||||
if ((FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS)) &&
|
||||
(FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS_BYPASS)))
|
||||
{ /* Access not allowed */
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for system to allow flash access */
|
||||
while (FD_Flash_Control_status & (1u << FD_FLASHACCESS_SYSTEM));
|
||||
|
||||
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, Dest, Payload) == HAL_OK)
|
||||
{
|
||||
status = FD_FLASHOP_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase one sector of Flash
|
||||
* @param Sect: Identifier of the sector to erase
|
||||
* @retval FD_FlashOp_Status_t: Success or failure of Flash erase operation
|
||||
*/
|
||||
FD_FlashOp_Status_t FD_EraseSectors(uint32_t Sect)
|
||||
{
|
||||
FD_FlashOp_Status_t status = FD_FLASHOP_FAILURE;
|
||||
uint32_t page_error;
|
||||
FLASH_EraseInitTypeDef p_erase_init;
|
||||
|
||||
#ifndef FLASH_DBANK_SUPPORT
|
||||
if (FLASH_PAGE_NB < Sect)
|
||||
#else
|
||||
if ((FLASH_PAGE_NB * 2u) < Sect)
|
||||
#endif
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Check if LL allows flash access */
|
||||
if ((FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS)) &&
|
||||
(FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS_BYPASS)))
|
||||
{ /* Access not allowed */
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for system to allow flash access */
|
||||
while (FD_Flash_Control_status & (1u << FD_FLASHACCESS_SYSTEM));
|
||||
|
||||
p_erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
p_erase_init.Page = (Sect & (FLASH_PAGE_NB - 1u));
|
||||
p_erase_init.NbPages = 1;
|
||||
|
||||
#if defined(FLASH_DBANK_SUPPORT)
|
||||
/* Verify which Bank is impacted */
|
||||
if ((FLASH_PAGE_NB <= Sect) ^ (OB_SWAP_BANK_ENABLE == READ_BIT (FLASH->OPTR, FLASH_OPTR_SWAP_BANK_Msk)))
|
||||
{
|
||||
p_erase_init.Banks = FLASH_BANK_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_erase_init.Banks = FLASH_BANK_1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (HAL_FLASHEx_Erase(&p_erase_init, &page_error) == HAL_OK)
|
||||
{
|
||||
status = FD_FLASHOP_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file flash_driver.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for flash_driver.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef FLASH_DRIVER_H
|
||||
#define FLASH_DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Bit mask to modify Flash Control status */
|
||||
typedef uint32_t FD_Flash_ctrl_bm_t;
|
||||
|
||||
/* Flash operation status */
|
||||
typedef enum
|
||||
{
|
||||
FD_FLASHOP_SUCCESS,
|
||||
FD_FLASHOP_FAILURE
|
||||
} FD_FlashOp_Status_t;
|
||||
|
||||
/* Flash Driver commands to enable or disable flash access */
|
||||
typedef enum
|
||||
{
|
||||
LL_FLASH_ENABLE,
|
||||
LL_FLASH_DISABLE,
|
||||
} FD_FLASH_Status_t;
|
||||
|
||||
/**
|
||||
* @brief Bit mask to modify Flash Control status
|
||||
*
|
||||
* @details Those bitmasks are used to enable/disable access to the flash:
|
||||
* - System:
|
||||
* -# FD_FLASHACCESS_SYSTEM: Determine whether or not the flash access is allowed from a system POV.
|
||||
* This bit has a predominance over all the other bit masks, ie: No flash operation can
|
||||
* be achieved without this to be set to 0, ie: LL_FLASH_ENABLE.
|
||||
* - RFTS:
|
||||
* -# FD_FLASHACCESS_RFTS: Determine whether or not the RF Timing Synchro allows flash access. This bit is set
|
||||
* once a window has been allowed by the BLE LL, ie: set to 0.
|
||||
* This bit has no impact when FD_FLASHACCESS_RFTS_BYPASS is set, ie: set to 0.
|
||||
* -# FD_FLASHACCESS_RFTS_BYPASS: Nullify the impact of FD_FLASHACCESS_RFTS when enabled, ie: set to 0. Its role is
|
||||
* to allow flash operation without the need to request a timing window to the RFTS,
|
||||
* ie: Executing flash operation without the BLE LL.
|
||||
*
|
||||
*/
|
||||
typedef enum FD_FlashAccess_bm
|
||||
{
|
||||
/* System flash access bitfield */
|
||||
FD_FLASHACCESS_SYSTEM,
|
||||
/* RF Timing Synchro flash access bitfield */
|
||||
FD_FLASHACCESS_RFTS,
|
||||
/* Bypass of RF Timing Synchro flash access bitfield */
|
||||
FD_FLASHACCESS_RFTS_BYPASS,
|
||||
}FD_FlashAccess_bm_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void FD_SetStatus(FD_Flash_ctrl_bm_t Flags_bm, FD_FLASH_Status_t Status);
|
||||
FD_FlashOp_Status_t FD_WriteData(uint32_t Dest, uint32_t Payload);
|
||||
FD_FlashOp_Status_t FD_EraseSectors(uint32_t Sect);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*FLASH_DRIVER_H */
|
||||
@@ -0,0 +1,516 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file flash_manager.c
|
||||
* @author MCD Application Team
|
||||
* @brief The Flash Manager module provides an interface to write raw data
|
||||
* from SRAM to FLASH
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdbool.h>
|
||||
#include "flash_manager.h"
|
||||
#include "rf_timing_synchro.h"
|
||||
#include "flash_driver.h"
|
||||
#include "utilities_conf.h"
|
||||
|
||||
#include "stm32wbaxx_hal.h"
|
||||
|
||||
/* Debug */
|
||||
#include "log_module.h"
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* State of the background process */
|
||||
typedef enum FM_BackGround_States
|
||||
{
|
||||
FM_BKGND_NOWINDOW_FLASHOP,
|
||||
FM_BKGND_WINDOWED_FLASHOP,
|
||||
}FM_BackGround_States_t;
|
||||
|
||||
/* Flash operation type */
|
||||
typedef enum
|
||||
{
|
||||
FM_WRITE_OP,
|
||||
FM_ERASE_OP
|
||||
} FM_FlashOp_t;
|
||||
|
||||
/**
|
||||
* @brief Flash operation configuration struct
|
||||
*/
|
||||
typedef struct FM_FlashOpConfig
|
||||
{
|
||||
uint32_t *writeSrc;
|
||||
uint32_t *writeDest;
|
||||
int32_t writeSize;
|
||||
uint32_t eraseFirstSect;
|
||||
uint32_t eraseNbrSect;
|
||||
}FM_FlashOpConfig_t;
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define FLASH_PAGE_NBR (FLASH_SIZE / FLASH_PAGE_SIZE)
|
||||
|
||||
#define FLASH_WRITE_BLOCK_SIZE 4U
|
||||
#define ALIGNMENT_32 0x00000003
|
||||
#define ALIGNMENT_128 0x0000000F
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Semaphore on Flash
|
||||
*/
|
||||
static bool busy_flash_sem = FALSE;
|
||||
|
||||
/**
|
||||
* @brief Indicates if the flash manager module is available or not
|
||||
*/
|
||||
static bool flash_manager_busy = FALSE;
|
||||
|
||||
/**
|
||||
* @brief Parameters for Flash Write command
|
||||
*/
|
||||
static bool fm_window_granted = FALSE;
|
||||
|
||||
/**
|
||||
* @brief Callback node list for pending flash operation request
|
||||
*/
|
||||
static tListNode fm_cb_pending_list;
|
||||
|
||||
/**
|
||||
* @brief Pointer to current flash operation requester's callback
|
||||
*/
|
||||
static void (*fm_running_cb)(FM_FlashOp_Status_t);
|
||||
|
||||
/**
|
||||
* @brief Type of current flash operation (Write/Erase)
|
||||
*/
|
||||
static FM_FlashOp_t fm_flashop;
|
||||
|
||||
/**
|
||||
* @brief Parameters for Flash operation
|
||||
*/
|
||||
static FM_FlashOpConfig_t fm_flashop_parameters;
|
||||
|
||||
/**
|
||||
* @brief State of the Background process
|
||||
*/
|
||||
static FM_BackGround_States_t FM_CurrentBackGroundState;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
static FM_Cmd_Status_t FM_CheckFlashManagerState(FM_CallbackNode_t *CallbackNode);
|
||||
static void FM_WindowAllowed_Callback(void);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the Flash manager module
|
||||
*/
|
||||
void FM_Init (void)
|
||||
{
|
||||
static bool fm_cb_pending_list_init = false;
|
||||
|
||||
/* Initialize pending list if not done */
|
||||
if (fm_cb_pending_list_init == false)
|
||||
{
|
||||
LST_init_head(&fm_cb_pending_list);
|
||||
fm_cb_pending_list_init = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request the Flash Manager module to initiate a Flash Write operation
|
||||
* @param Src: Address of the data to be stored in FLASH. It shall be 32bits aligned
|
||||
* @param Dest: Address where the data shall be written. It shall be 128bits aligned
|
||||
* @param Size: This is the size of data to be written in Flash.
|
||||
The size is a multiple of 32bits (size = 1 means 32bits)
|
||||
* @param CallbackNode: Pointer to the callback node for storage in list
|
||||
* @retval FM_Cmd_Status_t: Status of the Flash Manager module
|
||||
*/
|
||||
FM_Cmd_Status_t FM_Write(uint32_t *Src, uint32_t *Dest, int32_t Size, FM_CallbackNode_t *CallbackNode)
|
||||
{
|
||||
FM_Cmd_Status_t status;
|
||||
|
||||
if (((uint32_t)Dest < FLASH_BASE) || ((uint32_t)Dest > (FLASH_BASE + FLASH_SIZE))
|
||||
|| (((uint32_t)Dest + Size) > (FLASH_BASE + FLASH_SIZE)))
|
||||
{
|
||||
LOG_ERROR_SYSTEM("\r\nFM_Write - Destination address not part of the flash");
|
||||
|
||||
/* Destination address not part of the flash */
|
||||
return FM_ERROR;
|
||||
}
|
||||
|
||||
if (((uint32_t) Src & ALIGNMENT_32) || ((uint32_t) Dest & ALIGNMENT_128))
|
||||
{
|
||||
LOG_ERROR_SYSTEM("\r\nFM_Write - Source or destination address not properly aligned");
|
||||
|
||||
/* Source or destination address not properly aligned */
|
||||
return FM_ERROR;
|
||||
}
|
||||
|
||||
status = FM_CheckFlashManagerState(CallbackNode);
|
||||
|
||||
if (status == FM_OK)
|
||||
{ /* Flash manager is available */
|
||||
|
||||
/* Save Write parameters */
|
||||
fm_flashop_parameters.writeSrc = Src;
|
||||
fm_flashop_parameters.writeDest = Dest;
|
||||
fm_flashop_parameters.writeSize = Size;
|
||||
|
||||
fm_flashop = FM_WRITE_OP;
|
||||
|
||||
FM_CurrentBackGroundState = FM_BKGND_NOWINDOW_FLASHOP;
|
||||
|
||||
/* Window request to be executed in background */
|
||||
FM_ProcessRequest();
|
||||
}
|
||||
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_Write - Returned value : %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request the Flash Manager module to initiate a Flash Erase operation
|
||||
* @param FirstSect: Index of the first sector to erase
|
||||
* @param NbrSect: Number of sector to erase
|
||||
* @param CallbackNode: Pointer to the callback node for storage in list
|
||||
* @retval FM_Cmd_Status_t: Status of the Flash Manager module
|
||||
*/
|
||||
FM_Cmd_Status_t FM_Erase(uint32_t FirstSect, uint32_t NbrSect, FM_CallbackNode_t *CallbackNode)
|
||||
{
|
||||
FM_Cmd_Status_t status;
|
||||
|
||||
if ((FirstSect > FLASH_PAGE_NBR) || ((FirstSect + NbrSect) > FLASH_PAGE_NBR))
|
||||
{
|
||||
LOG_ERROR_SYSTEM("\r\nFM_Erase - Inconsistent request");
|
||||
|
||||
/* Inconsistent request */
|
||||
return FM_ERROR;
|
||||
}
|
||||
|
||||
if (NbrSect == 0)
|
||||
{
|
||||
LOG_ERROR_SYSTEM("\r\nFM_Erase - Inconsistent request");
|
||||
|
||||
/* Inconsistent request */
|
||||
return FM_ERROR;
|
||||
}
|
||||
|
||||
status = FM_CheckFlashManagerState(CallbackNode);
|
||||
|
||||
if (status == FM_OK)
|
||||
{ /* Flash manager is available */
|
||||
|
||||
/* Save Erase parameters */
|
||||
fm_flashop_parameters.eraseFirstSect = FirstSect;
|
||||
fm_flashop_parameters.eraseNbrSect = NbrSect;
|
||||
|
||||
fm_flashop = FM_ERASE_OP;
|
||||
|
||||
FM_CurrentBackGroundState = FM_BKGND_NOWINDOW_FLASHOP;
|
||||
|
||||
/* Window request to be executed in background */
|
||||
FM_ProcessRequest();
|
||||
}
|
||||
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_Erase - Returned value : %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Execute Flash Manager background tasks
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void FM_BackgroundProcess (void)
|
||||
{
|
||||
static uint32_t duration;
|
||||
bool flashop_complete = false;
|
||||
FD_FlashOp_Status_t fdReturnValue = FD_FLASHOP_SUCCESS;
|
||||
FM_CallbackNode_t *pCbNode = NULL;
|
||||
|
||||
switch (FM_CurrentBackGroundState)
|
||||
{
|
||||
case FM_BKGND_NOWINDOW_FLASHOP:
|
||||
{
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP");
|
||||
|
||||
if (fm_flashop == FM_WRITE_OP)
|
||||
{
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP - Write operation");
|
||||
|
||||
/* Update duration time value */
|
||||
duration = TIME_WINDOW_WRITE_REQUEST;
|
||||
|
||||
/* Set the next possible state - App could stop at anytime no window operation */
|
||||
FM_CurrentBackGroundState = FM_BKGND_WINDOWED_FLASHOP;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
while((fm_flashop_parameters.writeSize > 0) &&
|
||||
(fdReturnValue == FD_FLASHOP_SUCCESS))
|
||||
{
|
||||
fdReturnValue = FD_WriteData((uint32_t) fm_flashop_parameters.writeDest,
|
||||
(uint32_t) fm_flashop_parameters.writeSrc);
|
||||
|
||||
if (fdReturnValue == FD_FLASHOP_SUCCESS)
|
||||
{
|
||||
fm_flashop_parameters.writeDest += FLASH_WRITE_BLOCK_SIZE;
|
||||
fm_flashop_parameters.writeSrc += FLASH_WRITE_BLOCK_SIZE;
|
||||
fm_flashop_parameters.writeSize -= FLASH_WRITE_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
/* Is write over ? */
|
||||
if (fm_flashop_parameters.writeSize <= 0)
|
||||
{
|
||||
flashop_complete = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP - Erase operation");
|
||||
|
||||
/* Update duration time value */
|
||||
duration = TIME_WINDOW_ERASE_REQUEST;
|
||||
|
||||
/* Set the next possible state */
|
||||
FM_CurrentBackGroundState = FM_BKGND_WINDOWED_FLASHOP;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
while((fm_flashop_parameters.eraseNbrSect > 0) &&
|
||||
(fdReturnValue == FD_FLASHOP_SUCCESS))
|
||||
{
|
||||
fdReturnValue = FD_EraseSectors(fm_flashop_parameters.eraseFirstSect);
|
||||
|
||||
if (fdReturnValue == FD_FLASHOP_SUCCESS)
|
||||
{
|
||||
fm_flashop_parameters.eraseNbrSect--;
|
||||
fm_flashop_parameters.eraseFirstSect++;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
if (fm_flashop_parameters.eraseNbrSect == 0)
|
||||
{
|
||||
flashop_complete = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FM_BKGND_WINDOWED_FLASHOP:
|
||||
{
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP");
|
||||
|
||||
if (fm_window_granted == false)
|
||||
{
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - No time window granted yet, request one");
|
||||
|
||||
/* No time window granted yet, request one */
|
||||
RFTS_ReqWindow(duration, &FM_WindowAllowed_Callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Time window granted");
|
||||
|
||||
if (fm_flashop == FM_WRITE_OP)
|
||||
{
|
||||
/* Flash Write operation */
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Write operation");
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
while((fm_flashop_parameters.writeSize > 0) &&
|
||||
(FD_WriteData((uint32_t) fm_flashop_parameters.writeDest,
|
||||
(uint32_t) fm_flashop_parameters.writeSrc) == FD_FLASHOP_SUCCESS))
|
||||
{
|
||||
fm_flashop_parameters.writeDest += FLASH_WRITE_BLOCK_SIZE;
|
||||
fm_flashop_parameters.writeSrc += FLASH_WRITE_BLOCK_SIZE;
|
||||
fm_flashop_parameters.writeSize -= FLASH_WRITE_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (fm_flashop_parameters.writeSize <= 0)
|
||||
{
|
||||
flashop_complete = true;
|
||||
}
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Flash Erase operation */
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Erase operation");
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
/* Erase only one sector in a single time window */
|
||||
if (FD_EraseSectors(fm_flashop_parameters.eraseFirstSect) == FD_FLASHOP_SUCCESS)
|
||||
{
|
||||
fm_flashop_parameters.eraseNbrSect--;
|
||||
fm_flashop_parameters.eraseFirstSect++;
|
||||
}
|
||||
|
||||
if (fm_flashop_parameters.eraseNbrSect == 0)
|
||||
{
|
||||
flashop_complete = true;
|
||||
}
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
}
|
||||
|
||||
/* Release the time window */
|
||||
RFTS_RelWindow();
|
||||
|
||||
/* Indicate that there is no more window */
|
||||
fm_window_granted = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flashop_complete == true)
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
/* Release semaphore on flash */
|
||||
busy_flash_sem = false;
|
||||
|
||||
/* Set Flash Manager busy */
|
||||
flash_manager_busy = false;
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
/* Invoke the running callback if present */
|
||||
if (fm_running_cb != NULL)
|
||||
{
|
||||
fm_running_cb(FM_OPERATION_COMPLETE);
|
||||
}
|
||||
|
||||
/* notify pending requesters */
|
||||
while((LST_is_empty (&fm_cb_pending_list) == false) &&
|
||||
(busy_flash_sem == false) && (flash_manager_busy == false))
|
||||
{
|
||||
LST_remove_head (&fm_cb_pending_list, (tListNode**)&pCbNode);
|
||||
pCbNode->Callback(FM_OPERATION_AVAILABLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Flash operation not complete yet */
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Flash operation not complete yet, request a new time window");
|
||||
|
||||
/* Request a new time window */
|
||||
RFTS_ReqWindow(duration, &FM_WindowAllowed_Callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the Flash Manager is busy or available
|
||||
* @param CallbackNode: Pointer to the callback node for storage in list
|
||||
* @retval FM_Cmd_Status_t: Status of the Flash Manager module
|
||||
*/
|
||||
static FM_Cmd_Status_t FM_CheckFlashManagerState(FM_CallbackNode_t *CallbackNode)
|
||||
{
|
||||
bool fm_process_cmd = false;
|
||||
FM_Cmd_Status_t status = FM_ERROR;
|
||||
|
||||
/* Check if semaphore on flash is available */
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
/* Check if semaphore on flash is available */
|
||||
if (busy_flash_sem == false)
|
||||
{ /* Check if Flash Manager is already busy */
|
||||
if (flash_manager_busy == false)
|
||||
{
|
||||
busy_flash_sem = true; /* Get semaphore on flash */
|
||||
flash_manager_busy = true; /* Set Flash Manager busy */
|
||||
fm_process_cmd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fm_process_cmd = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fm_process_cmd = false;
|
||||
}
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
if (fm_process_cmd == false)
|
||||
{ /* Flash manager busy */
|
||||
|
||||
/* Append callback to the pending list */
|
||||
if ((CallbackNode != NULL) && (CallbackNode->Callback != NULL))
|
||||
{
|
||||
LST_insert_tail(&fm_cb_pending_list, &(CallbackNode->NodeList));
|
||||
}
|
||||
|
||||
status = FM_BUSY;
|
||||
}
|
||||
else
|
||||
{ /* Flash manager is available */
|
||||
|
||||
if ((CallbackNode != NULL) && (CallbackNode->Callback != NULL))
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
fm_running_cb = CallbackNode->Callback;
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
fm_running_cb = NULL;
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
status = FM_OK;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback called by RF Timing Synchro module when a time window is available
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void FM_WindowAllowed_Callback(void)
|
||||
{
|
||||
fm_window_granted = true;
|
||||
|
||||
LOG_DEBUG_SYSTEM("\r\nFM_WindowAllowed_Callback");
|
||||
|
||||
/* Flash operation to be executed in background */
|
||||
FM_ProcessRequest();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file flash_manager.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for flash_manager.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2023 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef FLASH_MANAGER_H
|
||||
#define FLASH_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
#include "stm_list.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Flash Manager command status */
|
||||
typedef enum
|
||||
{
|
||||
FM_OK, /* The Flash Manager is available and a window request is scheduled */
|
||||
FM_BUSY, /* The Flash Manager is busy and the caller will be called back when it is available */
|
||||
FM_ERROR /* An error occurred while processing the command */
|
||||
} FM_Cmd_Status_t;
|
||||
|
||||
/* Flash operation status */
|
||||
typedef enum
|
||||
{
|
||||
FM_OPERATION_COMPLETE, /* The requested flash operation is complete */
|
||||
FM_OPERATION_AVAILABLE /* A flash operation can be requested */
|
||||
} FM_FlashOp_Status_t;
|
||||
|
||||
/**
|
||||
* @brief Flash Manager callback node type to store them in a chained list
|
||||
*/
|
||||
typedef struct FM_CallbackNode
|
||||
{
|
||||
tListNode NodeList; /* Next and previous nodes in the list */
|
||||
void (*Callback)(FM_FlashOp_Status_t Status); /* Callback function pointer for Flash Manager caller */
|
||||
}FM_CallbackNode_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
#define TIME_WINDOW_ERASE_DURATION 4000U /* Duration in us of the time window requested for Flash Erase */
|
||||
#define TIME_WINDOW_WRITE_DURATION 1000U /* Duration in us of the time window requested for Flash Write */
|
||||
#define TIME_WINDOW_MARGIN 100U /* Time margin added so to ensure timeout protection before actual closure */
|
||||
/* As timers use ms, amount below 1000 is removed at conversion */
|
||||
#define TIME_WINDOW_ERASE_REQUEST (TIME_WINDOW_ERASE_DURATION + TIME_WINDOW_MARGIN)
|
||||
#define TIME_WINDOW_WRITE_REQUEST (TIME_WINDOW_WRITE_DURATION + TIME_WINDOW_MARGIN)
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void FM_Init (void);
|
||||
FM_Cmd_Status_t FM_Write(uint32_t *Src, uint32_t *Dest, int32_t Size, FM_CallbackNode_t *CallbackNode);
|
||||
FM_Cmd_Status_t FM_Erase(uint32_t FirstSect, uint32_t NbrSect, FM_CallbackNode_t *CallbackNode);
|
||||
void FM_BackgroundProcess (void);
|
||||
void FM_ProcessRequest (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*FLASH_MANAGER_H */
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf_timing_synchro.c
|
||||
* @author MCD Application Team
|
||||
* @brief The RF Timing Synchronization module provides an interface to
|
||||
* synchronize the flash processing versus the RF activity to make
|
||||
* sure the RF timing is not broken
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "rf_timing_synchro.h"
|
||||
#include "evnt_schdlr_gnrc_if.h"
|
||||
#include "utilities_conf.h"
|
||||
#include "stm32_timer.h"
|
||||
#include "flash_driver.h"
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
|
||||
/**
|
||||
* @brief Pointer to time window requester's callback
|
||||
*/
|
||||
static void (*req_callback)(void);
|
||||
|
||||
/**
|
||||
* @brief Indicates if a time window has already been requested or not
|
||||
*/
|
||||
static bool rfts_window_req_pending = FALSE;
|
||||
|
||||
/**
|
||||
* @brief Timer used by the RFTS module to prevent time window overrun
|
||||
*/
|
||||
static UTIL_TIMER_Object_t rfts_timer;
|
||||
|
||||
/**
|
||||
* @brief Firmware Link Layer external event handler
|
||||
*/
|
||||
static ext_evnt_hndl_t ext_event_handler;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
static void RFTS_WindowAllowed_Callback(void);
|
||||
static void RFTS_Timeout_Callback(void* Argument);
|
||||
static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr);
|
||||
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Request a time window to the Firmware Link Layer
|
||||
* @param duration: Duration in us of the time window requested
|
||||
* @param Callback: Callback to be called when time window is allocated
|
||||
* @retval RFTS_Cmd_Status_t: Success or failure of the window request
|
||||
*/
|
||||
RFTS_Cmd_Status_t RFTS_ReqWindow(uint32_t Duration, void (*Callback)(void))
|
||||
{
|
||||
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
|
||||
extrnl_evnt_st_t extrnl_evnt_config;
|
||||
bool req_pending = false;
|
||||
|
||||
if (Callback == NULL)
|
||||
{ /* Prevent use of uninitialized callback */
|
||||
return RFTS_WINDOW_REQ_FAILED;
|
||||
}
|
||||
|
||||
/* Check no request is already pending */
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
if (rfts_window_req_pending == true)
|
||||
{
|
||||
req_pending = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfts_window_req_pending = true;
|
||||
}
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
if (req_pending == true)
|
||||
{ /* A window request is already pending */
|
||||
return RFTS_WINDOW_REQ_FAILED;
|
||||
}
|
||||
|
||||
/* Register requester's callback */
|
||||
req_callback = Callback;
|
||||
|
||||
/* Submit request to Firmware Link Layer */
|
||||
extrnl_evnt_config.deadline = 0;
|
||||
extrnl_evnt_config.strt_min = 0;
|
||||
extrnl_evnt_config.strt_max = 0;
|
||||
extrnl_evnt_config.durn_min = Duration;
|
||||
extrnl_evnt_config.durn_max = 0;
|
||||
extrnl_evnt_config.prdc_intrvl = 0;
|
||||
extrnl_evnt_config.priority = PRIORITY_DEFAULT;
|
||||
extrnl_evnt_config.blocked = STATE_NOT_BLOCKED;
|
||||
extrnl_evnt_config.ptr_priv = NULL;
|
||||
extrnl_evnt_config.evnt_strtd_cbk = &event_started_callback;
|
||||
extrnl_evnt_config.evnt_blckd_cbk = NULL;
|
||||
extrnl_evnt_config.evnt_abortd_cbk = NULL;
|
||||
|
||||
UTIL_TIMER_Create(&rfts_timer,
|
||||
(Duration/1000),
|
||||
UTIL_TIMER_ONESHOT,
|
||||
&RFTS_Timeout_Callback,
|
||||
NULL);
|
||||
|
||||
ext_event_handler = evnt_schdlr_rgstr_gnrc_evnt(&extrnl_evnt_config);
|
||||
if (ext_event_handler == NULL)
|
||||
{
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
rfts_window_req_pending = false;
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
return RFTS_WINDOW_REQ_FAILED;
|
||||
}
|
||||
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
|
||||
|
||||
return RFTS_CMD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Execute necessary tasks to allow the time window to be released
|
||||
* @param None
|
||||
* @retval RFTS_Cmd_Status_t: Success or error in the window release procedure
|
||||
*/
|
||||
RFTS_Cmd_Status_t RFTS_RelWindow(void)
|
||||
{
|
||||
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
|
||||
RFTS_Cmd_Status_t status;
|
||||
|
||||
/* Stop RFTS module window overrun control timer */
|
||||
UTIL_TIMER_Stop(&rfts_timer);
|
||||
|
||||
/* Inform Firmware Link Layer that time window can be released */
|
||||
if (evnt_schdlr_gnrc_evnt_cmplt(ext_event_handler) == 0)
|
||||
{
|
||||
status = RFTS_CMD_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = RFTS_WINDOW_REL_ERROR;
|
||||
}
|
||||
|
||||
/* Forbid flash operation */
|
||||
FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE);
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
rfts_window_req_pending = false;
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
return status;
|
||||
#else
|
||||
return RFTS_CMD_OK;
|
||||
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
|
||||
}
|
||||
|
||||
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
|
||||
/**
|
||||
* @brief Callback called by Firmware Link Layer when a time window is available
|
||||
* @note This callback is supposed to be called under interrupt
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void RFTS_WindowAllowed_Callback(void)
|
||||
{
|
||||
/* Allow flash operation */
|
||||
FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_ENABLE);
|
||||
|
||||
/* Start timer preventing window overrun */
|
||||
UTIL_TIMER_Start(&rfts_timer);
|
||||
|
||||
/* Call back requester to inform time window is available */
|
||||
req_callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback triggered by a timeout when the allocated window time is elapsed
|
||||
* @note This callback is supposed to be called under interrupt
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void RFTS_Timeout_Callback(void* Argument)
|
||||
{
|
||||
/* Forbid flash operation */
|
||||
FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE);
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
rfts_window_req_pending = false;
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr)
|
||||
{
|
||||
RFTS_WindowAllowed_Callback();
|
||||
return 0;
|
||||
}
|
||||
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf_timing_synchro.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for rf_timing_synchro.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef RF_TIMING_SYNCHRO_H
|
||||
#define RF_TIMING_SYNCHRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* RFTS command status */
|
||||
typedef enum
|
||||
{
|
||||
RFTS_CMD_OK, /* The RF Timing synchronization command was successfully executed */
|
||||
RFTS_WINDOW_REQ_FAILED, /* The RF Timing synchronization module failed to register the window request */
|
||||
RFTS_WINDOW_REL_ERROR /* An error occurred during the window release procedure */
|
||||
} RFTS_Cmd_Status_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
RFTS_Cmd_Status_t RFTS_ReqWindow(uint32_t Duration, void (*Callback)(void));
|
||||
RFTS_Cmd_Status_t RFTS_RelWindow(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*RF_TIMING_SYNCHRO_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file simple_nvm_arbiter.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for simple_nvm_arbiter.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2023 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SIMPLE_NVM_ARBITER_H
|
||||
#define SIMPLE_NVM_ARBITER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "simple_nvm_arbiter_common.h"
|
||||
#include "simple_nvm_arbiter_conf.h"
|
||||
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Initialize the Simple NVM Arbiter
|
||||
*
|
||||
* @param p_NvmStartAddress: Start address of the NVM to work with - Shall be aligned 128 bits
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_ALREADY_INIT
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_NULL
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_NOT_ALIGNED
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_OVERLAP_FLASH
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_CRC_INIT
|
||||
*/
|
||||
SNVMA_Cmd_Status_t SNVMA_Init (const uint32_t * p_NvmStartAddress);
|
||||
|
||||
/**
|
||||
* @brief Register a user buffer to a NVM
|
||||
*
|
||||
* @details Buffer IDs are hardcoded, please refer to SNVMA_BufferId_t enumeration
|
||||
*
|
||||
* @param BufferId: Id of the user which ask for buffer registration
|
||||
* @param p_BufferAddress: Address of the buffer to be registered - Shall be aligned 32 bits
|
||||
* @param BufferSize: Size of the buffer to be registered - Shall be a multiple of 32bits
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOT_INIT
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_CMD_PENDING
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_KNOWN
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_NULL
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_NOT_ALIGNED
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_SIZE
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_BUFFER_FULL
|
||||
*/
|
||||
SNVMA_Cmd_Status_t SNVMA_Register (const SNVMA_BufferId_t BufferId,
|
||||
const uint32_t * p_BufferAddress,
|
||||
const uint32_t BufferSize);
|
||||
|
||||
/**
|
||||
* @brief Restore a user buffer from a NVM
|
||||
*
|
||||
* @details The user buffer information shall first be provided by calling SNVMA_Register
|
||||
*
|
||||
* @details Buffer IDs are hardcoded, please refer to SNVMA_BufferId_t enumeration
|
||||
*
|
||||
* @param BufferId: Id of the user which ask for buffer registration
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOT_INIT
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_CMD_PENDING
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_KNOWN
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_REGISTERED
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_BANK_EMPTY
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_BANK_CORRUPTED
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_CONFIG_MISSMATCH
|
||||
*/
|
||||
SNVMA_Cmd_Status_t SNVMA_Restore (const SNVMA_BufferId_t BufferId);
|
||||
|
||||
/**
|
||||
* @brief Register a user buffer to a NVM
|
||||
*
|
||||
* @details The user buffer information shall first be provided by calling SNVMA_Register
|
||||
*
|
||||
* @details Buffer IDs are hardcoded, please refer to SNVMA_BufferId_t enumeration
|
||||
*
|
||||
* @details A buffer write request cannot be scheduled once its NVM is already on a write operation. This will lead
|
||||
* to a SNVMA_OPERATION_FAILED callback status.
|
||||
*
|
||||
* @param BufferId: Id of the user which ask for buffer registration
|
||||
* @param Callback: Callback function for operation status return - Can be NULL
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOT_INIT
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_KNOWN
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_REGISTERED
|
||||
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_FLASH_ERROR
|
||||
*/
|
||||
SNVMA_Cmd_Status_t SNVMA_Write (const SNVMA_BufferId_t BufferId,
|
||||
void (* Callback) (SNVMA_Callback_Status_t));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*SIMPLE_NVM_ARBITER_H */
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file simple_nvm_arbiter_common.h
|
||||
* @author MCD Application Team
|
||||
* @brief Common header of simple_nvm_arbiter.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SIMPLE_NVM_ARBITER_COMMON_H
|
||||
#define SIMPLE_NVM_ARBITER_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Maximum number of different NVM Identifiers */
|
||||
#define SNVMA_MAX_NUMBER_NVM 32u
|
||||
|
||||
/* Maximum number of buffer per NVM */
|
||||
#define SNVMA_MAX_NUMBER_BUFFER 4u
|
||||
|
||||
/* Minimum number of bank per NVM */
|
||||
#define SNVMA_MIN_NUMBER_BANK 2u
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* SNVMA command status */
|
||||
typedef enum SNVMA_Cmd_Status
|
||||
{
|
||||
SNVMA_ERROR_OK,
|
||||
SNVMA_ERROR_NOK,
|
||||
SNVMA_ERROR_NOT_INIT,
|
||||
SNVMA_ERROR_ALREADY_INIT,
|
||||
SNVMA_ERROR_CMD_PENDING,
|
||||
SNVMA_ERROR_BANK_OP_ONGOING,
|
||||
SNVMA_ERROR_NVM_NULL,
|
||||
SNVMA_ERROR_NVM_NOT_ALIGNED,
|
||||
SNVMA_ERROR_NVM_OVERLAP_FLASH,
|
||||
SNVMA_ERROR_NVM_BUFFER_FULL,
|
||||
SNVMA_ERROR_NVM_BANK_EMPTY,
|
||||
SNVMA_ERROR_NVM_BANK_CORRUPTED,
|
||||
SNVMA_ERROR_CRC_INIT,
|
||||
SNVMA_ERROR_BANK_NUMBER,
|
||||
SNVMA_ERROR_BANK_SIZE,
|
||||
SNVMA_ERROR_BUFFERID_NOT_KNOWN,
|
||||
SNVMA_ERROR_BUFFERID_NOT_REGISTERED,
|
||||
SNVMA_ERROR_BUFFER_NULL,
|
||||
SNVMA_ERROR_BUFFER_NOT_ALIGNED,
|
||||
SNVMA_ERROR_BUFFER_SIZE,
|
||||
SNVMA_ERROR_BUFFER_CONFIG_MISSMATCH,
|
||||
SNVMA_ERROR_FLASH_ERROR,
|
||||
SNVMA_ERROR_UNKNOWN,
|
||||
} SNVMA_Cmd_Status_t;
|
||||
|
||||
/* SNVMA callback status */
|
||||
typedef enum SNVMA_Callback_Status
|
||||
{
|
||||
SNVMA_OPERATION_COMPLETE,
|
||||
SNVMA_OPERATION_FAILED
|
||||
}SNVMA_Callback_Status_t;
|
||||
|
||||
/* Buffer Element */
|
||||
typedef struct SNVMA_BufferElt
|
||||
{
|
||||
/* Buffer address */
|
||||
uint32_t * p_Addr;
|
||||
/* Buffer size */
|
||||
uint32_t Size;
|
||||
}SNVMA_BufferElt_t;
|
||||
|
||||
/* Bank Element */
|
||||
typedef struct SNVMA_BankElt
|
||||
{
|
||||
/* Pointer onto the start address of the bank */
|
||||
uint32_t * p_StartAddr;
|
||||
/* Pointer onto the buffer address in the bank */
|
||||
uint32_t * ap_BufferAddr[SNVMA_MAX_NUMBER_BUFFER];
|
||||
}SNVMA_BankElt_t;
|
||||
|
||||
/* NVM Element */
|
||||
typedef struct SNVMA_NvmElt
|
||||
{
|
||||
/* Bank number */
|
||||
uint8_t BankNumber;
|
||||
/* Bank size */
|
||||
uint8_t BankSize;
|
||||
/*
|
||||
* Pending buffer write operations bit mask
|
||||
*
|
||||
* ----------------------------------------
|
||||
* + 4 bits | 4 bits +
|
||||
* + ------------------------------------ +
|
||||
* + Active Request | New Request +
|
||||
* ----------------------------------------
|
||||
*
|
||||
*/
|
||||
uint8_t PendingBufferWriteOp;
|
||||
/* Pointer onto the bank list */
|
||||
SNVMA_BankElt_t * p_BankList;
|
||||
/* Pointer onto the bank being used for write operation */
|
||||
SNVMA_BankElt_t * p_BankForWrite;
|
||||
/* Pointer onto the bank being used for restore operation */
|
||||
SNVMA_BankElt_t * p_BankForRestore;
|
||||
/* Callback pointer array */
|
||||
void (* a_Callback [SNVMA_MAX_NUMBER_BUFFER]) (SNVMA_Callback_Status_t);
|
||||
/* Array of buffers in use */
|
||||
SNVMA_BufferElt_t a_Buffers [SNVMA_MAX_NUMBER_BUFFER];
|
||||
}SNVMA_NvmElt_t;
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*SIMPLE_NVM_ARBITER_COMMON_H */
|
||||
@@ -0,0 +1,298 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file log_module.c
|
||||
* @author MCD Application Team
|
||||
* @brief Source file of the log module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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 <stdio.h> /* vsnprintf */
|
||||
|
||||
#include "log_module.h"
|
||||
#include "stm32_adv_trace.h"
|
||||
#include "utilities_conf.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Definition of 'End Of Line' */
|
||||
#define ENDOFLINE_SIZE (0x01u)
|
||||
#define ENDOFLINE_CHAR '\n'
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Global const struct variables to make the life of the user easier */
|
||||
const Log_Module_t LOG_MODULE_DEFAULT_CONFIGURATION =
|
||||
{
|
||||
.verbose_level = LOG_VERBOSE_ERROR,
|
||||
.region_mask = (LOG_REGION_ALL_REGIONS)
|
||||
};
|
||||
|
||||
const Log_Verbose_Level_t LOG_VERBOSE_DEFAULT = LOG_VERBOSE_ERROR;
|
||||
const Log_Region_t LOG_REGION_MASK_DEFAULT = LOG_REGION_ALL_REGIONS;
|
||||
const Log_Color_t LOG_COLOR_DEFAULT_CONFIGURATION[] =
|
||||
{
|
||||
LOG_COLOR_CODE_DEFAULT, // For Region BLE
|
||||
LOG_COLOR_CODE_DEFAULT, // For Region System
|
||||
LOG_COLOR_CODE_DEFAULT, // For Region APP
|
||||
LOG_COLOR_CODE_RED, // For Region LinkLayer
|
||||
LOG_COLOR_CODE_YELLOW, // For Region MAC
|
||||
LOG_COLOR_CODE_GREEN, // For Region Zigbee
|
||||
LOG_COLOR_CODE_GREEN, // For Region Thread
|
||||
LOG_COLOR_CODE_DEFAULT, // For Region RTOS
|
||||
/* USER CODE BEGIN LOG_COLOR_DEFAULT_CONFIGURATION */
|
||||
|
||||
/* USER CODE END LOG_COLOR_DEFAULT_CONFIGURATION */
|
||||
};
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
static uint32_t current_region_mask;
|
||||
static Log_Verbose_Level_t current_verbose_level;
|
||||
static Log_Color_t current_color_list[32];
|
||||
CallBack_TimeStamp * log_timestamp_function;
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static uint32_t Get_Region_Mask(Log_Region_t Region);
|
||||
|
||||
#if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
|
||||
static uint16_t RegionToColor(char * TextBuffer, uint16_t SizeMax, Log_Region_t Region);
|
||||
#endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
#if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
|
||||
/**
|
||||
* @brief Add the color (in function of Region) on the start of Log sentence.
|
||||
*
|
||||
* @param TextBuffer Pointer on the log buffer
|
||||
* @param SizeMax The maximum number of bytes that will be written to the buffer.
|
||||
* @param Region Region of the log to apply its corresponding color.
|
||||
*
|
||||
* @return Length of the new Log.
|
||||
*/
|
||||
static uint16_t RegionToColor(char * TextBuffer, uint16_t SizeMax, Log_Region_t Region)
|
||||
{
|
||||
uint16_t text_length = 0;
|
||||
Log_Color_t color;
|
||||
static Log_Color_t previous_color = LOG_COLOR_NONE;
|
||||
|
||||
if (Region != LOG_MODULE_ALL_REGION_MASK)
|
||||
{
|
||||
color = current_color_list[Region];
|
||||
}
|
||||
else
|
||||
{
|
||||
color = LOG_COLOR_CODE_DEFAULT;
|
||||
}
|
||||
|
||||
/* Insert Color code only if previous is not the same */
|
||||
if (color != previous_color)
|
||||
{
|
||||
if (color == LOG_COLOR_CODE_DEFAULT)
|
||||
{
|
||||
snprintf(TextBuffer, SizeMax, "\x1b[0m");
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(TextBuffer, SizeMax, "\x1b[0;%02dm", color);
|
||||
}
|
||||
|
||||
previous_color = color;
|
||||
text_length = strlen(TextBuffer);
|
||||
}
|
||||
|
||||
return text_length;
|
||||
}
|
||||
#endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
|
||||
|
||||
void Log_Module_PrintWithArg(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, va_list Args)
|
||||
{
|
||||
uint16_t tmp_size = 0;
|
||||
uint16_t buffer_size = 0;
|
||||
char full_text[UTIL_ADV_TRACE_TMP_BUF_SIZE + 1u];
|
||||
|
||||
/* USER CODE BEGIN Log_Module_PrintWithArg_1 */
|
||||
|
||||
/* USER CODE END Log_Module_PrintWithArg_1 */
|
||||
|
||||
/* If the verbose level of the given log is not enabled, then we do not print the log */
|
||||
if (VerboseLevel > current_verbose_level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the region for the given log is not enabled, then we do not print the log */
|
||||
if ((Get_Region_Mask(Region) & current_region_mask) == 0u)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
|
||||
/* Add to full_text the color matching the region */
|
||||
tmp_size = RegionToColor(&full_text[buffer_size], (UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size), Region);
|
||||
buffer_size += tmp_size;
|
||||
#endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
|
||||
|
||||
#if (LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE != 0)
|
||||
if (log_timestamp_function != NULL)
|
||||
{
|
||||
tmp_size = UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size;
|
||||
log_timestamp_function(&full_text[buffer_size], tmp_size, &tmp_size);
|
||||
buffer_size += tmp_size;
|
||||
}
|
||||
#endif /* LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE != 0 */
|
||||
|
||||
/* Copy the data */
|
||||
tmp_size = (uint16_t)vsnprintf(&full_text[buffer_size], (UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size), Text, Args);
|
||||
buffer_size += tmp_size;
|
||||
|
||||
/* USER CODE BEGIN Log_Module_PrintWithArg_2 */
|
||||
|
||||
/* USER CODE END Log_Module_PrintWithArg_2 */
|
||||
|
||||
#if (LOG_INSERT_EOL_INSIDE_THE_TRACE != 0)
|
||||
/* Add End Of Line if needed */
|
||||
if (buffer_size > 1)
|
||||
{
|
||||
if ((full_text[buffer_size - 1] != ENDOFLINE_CHAR) && (full_text[buffer_size - 2] != ENDOFLINE_CHAR))
|
||||
{
|
||||
full_text[buffer_size++] = ENDOFLINE_CHAR;
|
||||
full_text[buffer_size] = 0;
|
||||
}
|
||||
}
|
||||
#endif /* LOG_INSERT_EOL_INSIDE_THE_TRACE != 0 */
|
||||
|
||||
/* USER CODE BEGIN Log_Module_PrintWithArg_3 */
|
||||
|
||||
/* USER CODE END Log_Module_PrintWithArg_3 */
|
||||
|
||||
/* Send full_text to ADV Traces */
|
||||
UTIL_ADV_TRACE_Send((const uint8_t *)full_text, buffer_size);
|
||||
}
|
||||
|
||||
void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...)
|
||||
{
|
||||
#if (CFG_LOG_SUPPORTED != 0)
|
||||
va_list variadic_args;
|
||||
|
||||
va_start(variadic_args, Text);
|
||||
Log_Module_PrintWithArg(VerboseLevel, Region, Text, variadic_args);
|
||||
va_end(variadic_args);
|
||||
#else /* (CFG_LOG_SUPPORTED != 0) */
|
||||
UNUSED(VerboseLevel);
|
||||
UNUSED(Region);
|
||||
UNUSED(Text);
|
||||
#endif /* (CFG_LOG_SUPPORTED != 0) */
|
||||
}
|
||||
|
||||
void Log_Module_Init(Log_Module_t LogConfiguration)
|
||||
{
|
||||
UTIL_ADV_TRACE_Init();
|
||||
|
||||
memcpy(¤t_color_list, &LOG_COLOR_DEFAULT_CONFIGURATION, sizeof(LOG_COLOR_DEFAULT_CONFIGURATION));
|
||||
Log_Module_Set_Verbose_Level(LogConfiguration.verbose_level);
|
||||
Log_Module_Set_Multiple_Regions(LogConfiguration.region_mask);
|
||||
log_timestamp_function = NULL;
|
||||
}
|
||||
|
||||
void Log_Module_DeInit(void)
|
||||
{
|
||||
UTIL_ADV_TRACE_DeInit();
|
||||
}
|
||||
|
||||
void Log_Module_Set_Verbose_Level(Log_Verbose_Level_t NewVerboseLevel)
|
||||
{
|
||||
current_verbose_level = NewVerboseLevel;
|
||||
}
|
||||
|
||||
void Log_Module_Set_Region(Log_Region_t NewRegion)
|
||||
{
|
||||
current_region_mask = Get_Region_Mask(NewRegion);
|
||||
}
|
||||
|
||||
void Log_Module_Add_Region(Log_Region_t NewRegion)
|
||||
{
|
||||
current_region_mask |= Get_Region_Mask(NewRegion);
|
||||
}
|
||||
|
||||
void Log_Module_Remove_Region(Log_Region_t Region)
|
||||
{
|
||||
current_region_mask &= ~Get_Region_Mask(Region);
|
||||
}
|
||||
|
||||
void Log_Module_Enable_All_Regions(void)
|
||||
{
|
||||
Log_Module_Set_Region(LOG_REGION_ALL_REGIONS);
|
||||
}
|
||||
|
||||
static uint32_t Get_Region_Mask(Log_Region_t Region)
|
||||
{
|
||||
if (Region == LOG_REGION_ALL_REGIONS)
|
||||
{
|
||||
/* Return the full mask */
|
||||
return ((uint32_t)LOG_MODULE_ALL_REGION_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return the bit matching the region */
|
||||
return ((uint32_t)(1U << ((uint32_t)Region)));
|
||||
}
|
||||
}
|
||||
|
||||
void Log_Module_Set_Multiple_Regions(uint32_t NewRegionMask)
|
||||
{
|
||||
current_region_mask = NewRegionMask;
|
||||
}
|
||||
|
||||
void Log_Module_Set_Color(Log_Region_t Region, Log_Color_t Color)
|
||||
{
|
||||
if ( Region != LOG_MODULE_ALL_REGION_MASK )
|
||||
{
|
||||
current_color_list[Region] = Color;
|
||||
}
|
||||
}
|
||||
|
||||
void Log_Module_RegisterTimeStampFunction(CallBack_TimeStamp * TimeStampFunction)
|
||||
{
|
||||
log_timestamp_function = TimeStampFunction;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
@@ -0,0 +1,220 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file log_module.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file of the log module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef LOG_MODULE_H
|
||||
#define LOG_MODULE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "log_module_conf.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Log module types */
|
||||
/**
|
||||
* @brief Data type to initialize the module by calling Log_Module_Init.
|
||||
* verbose_level : A value of type Log_Verbose_Level_t.
|
||||
* region_mask : A mask based on Log_Region_t.
|
||||
* You can directly assign it to LOG_REGION_ALL_REGIONS,
|
||||
* or select only some regions :
|
||||
* (1U << LOG_REGION_BLE | 1U << LOG_REGION_APP)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Log_Verbose_Level_t verbose_level;
|
||||
uint32_t region_mask;
|
||||
} Log_Module_t;
|
||||
|
||||
/**
|
||||
* @brief Callback function to insert Time Stamp.
|
||||
*
|
||||
* @param Data The data into which to insert the TimeStamp.
|
||||
* @param SizeMax The maximum size for the TimeStamp insert.
|
||||
* @param TimeStampSize Pointer to update with the size of the TimeStamp inserted into data.
|
||||
*/
|
||||
typedef void CallBack_TimeStamp(char * Data, uint16_t SizeMax, uint16_t * TimeStampSize);
|
||||
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Global const struct variables to make the life of the user easier */
|
||||
/**
|
||||
* @brief A const struct with default parameters for the log module.
|
||||
* Its main use is to pass it as parameter to Log_Module_Init.
|
||||
*/
|
||||
extern const Log_Module_t LOG_MODULE_DEFAULT_CONFIGURATION;
|
||||
|
||||
/**
|
||||
* @brief A const enum variable with the verbose level set to LOG_VERBOSE_ERROR.
|
||||
* The levels include the lower levels in the logs.
|
||||
*
|
||||
* E.g. LOG_VERBOSE_ERROR means LOG_VERBOSE_ERROR logs will be printed,
|
||||
* as well as LOG_VERBOSE_INFO, but not the others with higher values.
|
||||
*/
|
||||
extern const Log_Verbose_Level_t LOG_VERBOSE_DEFAULT;
|
||||
|
||||
/**
|
||||
* @brief A const enum variable to include all regions in the logs.
|
||||
*/
|
||||
extern const Log_Region_t LOG_REGION_MASK_DEFAULT;
|
||||
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
/* Module API - Module configuration */
|
||||
/**
|
||||
* @brief Initialization of the log module.
|
||||
*
|
||||
* @param LogConfiguration The configuration of the log module, of type Log_Module_t.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Init(Log_Module_t LogConfiguration);
|
||||
|
||||
/**
|
||||
* @brief DeInitialization of the log module.
|
||||
*
|
||||
* @param None.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_DeInit(void);
|
||||
|
||||
/**
|
||||
* @brief Set the verbose level of the log.
|
||||
* The levels include the lower levels in the logs.
|
||||
*
|
||||
* E.g. LOG_VERBOSE_ERROR means LOG_VERBOSE_ERROR logs will be printed,
|
||||
* as well as LOG_VERBOSE_INFO, but not the others with higher values.
|
||||
*
|
||||
* @param NewVerboseLevel The new verbose level to be set, of type Log_Verbose_Level_t
|
||||
* @return None
|
||||
*/
|
||||
void Log_Module_Set_Verbose_Level(Log_Verbose_Level_t NewVerboseLevel);
|
||||
|
||||
/**
|
||||
* @brief Replace the current regions in use and only set the given region.
|
||||
*
|
||||
* @param NewRegion The new region to use, of type Log_Region_t.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Set_Region(Log_Region_t NewRegion);
|
||||
|
||||
/**
|
||||
* @brief Replace the current regions in use and set one or several as replacement.
|
||||
*
|
||||
* @param NewRegionMask A mask, of type uint32_t, where each bit corresponds to a region.
|
||||
* You can directly assign it to LOG_REGION_ALL_REGIONS to enable all of them,
|
||||
* or select only some regions, e.g. (1U << LOG_REGION_BLE | 1U << LOG_REGION_APP)
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Set_Multiple_Regions(uint32_t NewRegionMask);
|
||||
|
||||
/**
|
||||
* @brief Add to the current region mask the given region.
|
||||
*
|
||||
* @param NewRegion The new region to use, alongside the others, of type Log_Region_t.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Add_Region(Log_Region_t NewRegion);
|
||||
|
||||
/**
|
||||
* @brief Remove from the current region mask the given region.
|
||||
*
|
||||
* @param Region The region to remove, of type Log_Region_t.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Remove_Region(Log_Region_t Region);
|
||||
|
||||
/**
|
||||
* @brief Enable all the regions.
|
||||
*
|
||||
* @param None.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Enable_All_Regions(void);
|
||||
|
||||
/**
|
||||
* @brief Set the color for a region.
|
||||
*
|
||||
* @param Region The region where apply the color, type Log_Region_t.
|
||||
* @param Color The color to apply to selected region, of type Log_Color_t.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Set_Color(Log_Region_t Region, Log_Color_t Color);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function to insert the TimeStamp into the data.
|
||||
*
|
||||
* @param TimeStampFunction Callback function to insert TimeStamp.
|
||||
* This function is typedef void (char * data, uint16_t size_max, uint16_t * timestamp_size);
|
||||
* Where data is the location where to insert the new TimeStamp, and timestamp_size is the size of this insertion.
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_RegisterTimeStampFunction(CallBack_TimeStamp * TimeStampFunction);
|
||||
|
||||
/* Module API - Wrapper function */
|
||||
/**
|
||||
* @brief Underlying function of all the LOG_xxx macros.
|
||||
*
|
||||
* @param VerboseLevel The level of verbose used for this Log, of type Log_Verbose_Level_t.
|
||||
* @param Region The region set for this log, of type Log_Region_t.
|
||||
* @param Text The text to be printed.
|
||||
* @param ... Any other parameters to be printed with the text.
|
||||
* E.g. an int variable. as 3rd parameter, as long as %d is in text.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...);
|
||||
|
||||
/**
|
||||
* @brief Function of log with already a arg list.
|
||||
*
|
||||
* @param VerboseLevel The level of verbose used for this Log, of type Log_Verbose_Level_t.
|
||||
* @param Region The region set for this log, of type Log_Region_t.
|
||||
* @param Text The text to be printed
|
||||
* @param Args Arguments list, of type va_list.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void Log_Module_PrintWithArg(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, va_list Args);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LOG_MODULE_H */
|
||||
@@ -0,0 +1,294 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file log_module_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file of the log module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef LOG_MODULE_CONF_H
|
||||
#define LOG_MODULE_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_conf.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Module configuration ------------------------------------------------------*/
|
||||
/**
|
||||
* @brief When this define is set to 0, there is no time stamp added to the trace data.
|
||||
* When this define is set to 1, the time stamp is added to the trace data,
|
||||
* according to the function registered with Log_Module_RegisterTimeStampFunction.
|
||||
*/
|
||||
#define LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE CFG_LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE
|
||||
|
||||
/**
|
||||
* @brief When this define is set to 0, the color of the trace data remains the same for all regions.
|
||||
* When this define is set to 1, the color added to the trace data is based on LOG_COLOR_DEFAULT_CONFIGURATION.
|
||||
*/
|
||||
#define LOG_INSERT_COLOR_INSIDE_THE_TRACE CFG_LOG_INSERT_COLOR_INSIDE_THE_TRACE
|
||||
|
||||
/**
|
||||
* @brief When this define is set to 0, the trace data is not modified.
|
||||
* When this define is set to 1, if there is no ENDOFLINE_CHAR as last
|
||||
* character in the trace data, then one is added.
|
||||
*/
|
||||
#define LOG_INSERT_EOL_INSIDE_THE_TRACE CFG_LOG_INSERT_EOL_INSIDE_THE_TRACE
|
||||
|
||||
/* USER CODE BEGIN Module configuration */
|
||||
|
||||
/* USER CODE END Module configuration */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* These defines are related to the UTIL_ADV_TRACE. Do not modify them please. */
|
||||
#define LOG_MODULE_MIN_VERBOSE_LEVEL (0)
|
||||
#define LOG_MODULE_MAX_VERBOSE_LEVEL (0xFFFFFFFF)
|
||||
#define LOG_MODULE_MIN_REGION_VALUE (0)
|
||||
#define LOG_MODULE_ALL_REGION_MASK (0xFFFFFFFF)
|
||||
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Log module types */
|
||||
/**
|
||||
* @brief Customizable enum describing the verbose levels used by the log module.
|
||||
* The levels include the lower levels in the logs.
|
||||
*
|
||||
* E.g. LOG_VERBOSE_ERROR means LOG_VERBOSE_ERROR logs will be printed,
|
||||
* as well as LOG_VERBOSE_INFO, but not the others with higher values.
|
||||
*
|
||||
* The min and max ranges are defined by LOG_MODULE_MIN_VERBOSE_LEVEL
|
||||
* and LOG_MODULE_MAX_VERBOSE_LEVEL.
|
||||
*
|
||||
* The user can add its own levels but must NOT add a value to the said
|
||||
* levels. Verbose levels are handled by the UTIL_ADV_TRACE.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LOG_VERBOSE_INFO = LOG_MODULE_MIN_VERBOSE_LEVEL,
|
||||
/* USER CODE BEGIN Log_Verbose_Level_t_0 */
|
||||
|
||||
/* USER CODE END Log_Verbose_Level_t_0 */
|
||||
LOG_VERBOSE_ERROR,
|
||||
/* USER CODE BEGIN Log_Verbose_Level_t_1 */
|
||||
|
||||
/* USER CODE END Log_Verbose_Level_t_1 */
|
||||
LOG_VERBOSE_WARNING,
|
||||
/* USER CODE BEGIN Log_Verbose_Level_t_2 */
|
||||
|
||||
/* USER CODE END Log_Verbose_Level_t_2 */
|
||||
LOG_VERBOSE_DEBUG,
|
||||
/* USER CODE BEGIN Log_Verbose_Level_t_3 */
|
||||
|
||||
/* USER CODE END Log_Verbose_Level_t_3 */
|
||||
LOG_VERBOSE_ALL_LOGS = LOG_MODULE_MAX_VERBOSE_LEVEL,
|
||||
} Log_Verbose_Level_t;
|
||||
|
||||
/**
|
||||
* @brief Customizable enum describing the regions used by the log module.
|
||||
* Regions are used to separate the logs into different places.
|
||||
*
|
||||
* Let's say you have a Task 1 and a Task 2.
|
||||
* Both of them have Info and Debug logs.
|
||||
*
|
||||
* By using them as such, i.e. with the same regions, you'll
|
||||
* print the logs of the 2 tasks as long as the verbose is Info or Debug.
|
||||
*
|
||||
* If you create a region for Task 1 and another for Task 2, you can
|
||||
* split the logs between them, and, if needed, only print the Debug
|
||||
* logs for Task 1 only (i.e. Task 1 logs for Info and Debug).
|
||||
*
|
||||
* Behind the scenes is a mask into which each region is a bit.
|
||||
* The user can add its own regions but must NOT add a value to them.
|
||||
* The log module handles the mask on its own.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LOG_REGION_BLE = LOG_MODULE_MIN_REGION_VALUE,
|
||||
LOG_REGION_SYSTEM,
|
||||
LOG_REGION_APP,
|
||||
LOG_REGION_LINKLAYER,
|
||||
LOG_REGION_MAC,
|
||||
LOG_REGION_ZIGBEE,
|
||||
LOG_REGION_THREAD,
|
||||
LOG_REGION_RTOS,
|
||||
/* USER CODE BEGIN Log_Region_t */
|
||||
|
||||
/* USER CODE END Log_Region_t */
|
||||
LOG_REGION_ALL_REGIONS = LOG_MODULE_ALL_REGION_MASK,
|
||||
} Log_Region_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LOG_COLOR_NONE = 0, /* Initialization */
|
||||
LOG_COLOR_CODE_DEFAULT = 37, /* White */
|
||||
LOG_COLOR_CODE_RED = 91,
|
||||
LOG_COLOR_CODE_GREEN = 92,
|
||||
LOG_COLOR_CODE_YELLOW = 93,
|
||||
LOG_COLOR_CODE_CYAN = 96,
|
||||
/* USER CODE BEGIN Log_Color_t */
|
||||
|
||||
/* USER CODE END Log_Color_t */
|
||||
} Log_Color_t;
|
||||
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Display 64 bits number for all compiler. */
|
||||
/* Example : LOG_INFO_APP( "New Device : " LOG_DISPLAY64() " installed in %d seconds", LOG_NUMBER64( dlDevice ), iTime ); */
|
||||
#define LOG_DISPLAY64() "0x%08X%08X"
|
||||
#define LOG_NUMBER64( number ) (uint32_t)( number >> 32u ), (uint32_t)( number )
|
||||
|
||||
/* Module API - Log macros for each region */
|
||||
/* LOG_REGION_BLE */
|
||||
#if (CFG_LOG_SUPPORTED != 0)
|
||||
#define LOG_INFO_BLE(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_BLE, __VA_ARGS__)
|
||||
#define LOG_ERROR_BLE(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_BLE, __VA_ARGS__)
|
||||
#define LOG_WARNING_BLE(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_BLE, __VA_ARGS__)
|
||||
#define LOG_DEBUG_BLE(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_BLE, __VA_ARGS__)
|
||||
#else /* (CFG_LOG_SUPPORTED != 0) */
|
||||
#define LOG_INFO_BLE(...) do {} while(0)
|
||||
#define LOG_ERROR_BLE(...) do {} while(0)
|
||||
#define LOG_WARNING_BLE(...) do {} while(0)
|
||||
#define LOG_DEBUG_BLE(...) do {} while(0)
|
||||
#endif /* (CFG_LOG_SUPPORTED != 0) */
|
||||
|
||||
/* USER CODE BEGIN LOG_REGION_BLE */
|
||||
/**
|
||||
* Add inside this user section your defines to match the new verbose levels you
|
||||
* created into Log_Verbose_Level_t.
|
||||
* Example :
|
||||
* #define LOG_CUSTOM_BLE(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_BLE, __VA_ARGS__);
|
||||
*
|
||||
* You don't need to update all regions with your custom values.
|
||||
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
|
||||
*/
|
||||
|
||||
/* USER CODE END LOG_REGION_BLE */
|
||||
|
||||
/* LOG_REGION_SYSTEM */
|
||||
#if (CFG_LOG_SUPPORTED != 0)
|
||||
#define LOG_INFO_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_SYSTEM, __VA_ARGS__)
|
||||
#define LOG_ERROR_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_SYSTEM, __VA_ARGS__)
|
||||
#define LOG_WARNING_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_SYSTEM, __VA_ARGS__)
|
||||
#define LOG_DEBUG_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_SYSTEM, __VA_ARGS__)
|
||||
#else /* (CFG_LOG_SUPPORTED != 0) */
|
||||
#define LOG_INFO_SYSTEM(...) do {} while(0)
|
||||
#define LOG_ERROR_SYSTEM(...) do {} while(0)
|
||||
#define LOG_WARNING_SYSTEM(...) do {} while(0)
|
||||
#define LOG_DEBUG_SYSTEM(...) do {} while(0)
|
||||
#endif /* (CFG_LOG_SUPPORTED != 0) */
|
||||
|
||||
/* USER CODE BEGIN LOG_REGION_SYSTEM */
|
||||
/**
|
||||
* Add inside this user section your defines to match the new verbose levels you
|
||||
* created into Log_Verbose_Level_t.
|
||||
* Example :
|
||||
* #define LOG_CUSTOM_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_SYSTEM, __VA_ARGS__);
|
||||
*
|
||||
* You don't need to update all regions with your custom values.
|
||||
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
|
||||
*/
|
||||
|
||||
/* USER CODE END LOG_REGION_SYSTEM */
|
||||
|
||||
/* LOG_REGION_APP */
|
||||
#if (CFG_LOG_SUPPORTED != 0)
|
||||
#define LOG_INFO_APP(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_APP, __VA_ARGS__)
|
||||
#define LOG_ERROR_APP(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_APP, __VA_ARGS__)
|
||||
#define LOG_WARNING_APP(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_APP, __VA_ARGS__)
|
||||
#define LOG_DEBUG_APP(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_APP, __VA_ARGS__)
|
||||
#else /* (CFG_LOG_SUPPORTED != 0) */
|
||||
#define LOG_INFO_APP(...) do {} while(0)
|
||||
#define LOG_ERROR_APP(...) do {} while(0)
|
||||
#define LOG_WARNING_APP(...) do {} while(0)
|
||||
#define LOG_DEBUG_APP(...) do {} while(0)
|
||||
#endif /* (CFG_LOG_SUPPORTED != 0) */
|
||||
|
||||
/* USER CODE BEGIN LOG_REGION_APP */
|
||||
/**
|
||||
* Add inside this user section your defines to match the new verbose levels you
|
||||
* created into Log_Verbose_Level_t.
|
||||
* Example :
|
||||
* #define LOG_CUSTOM_APP(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_APP, __VA_ARGS__);
|
||||
*
|
||||
* You don't need to update all regions with your custom values.
|
||||
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
|
||||
*/
|
||||
|
||||
/* USER CODE END LOG_REGION_APP */
|
||||
|
||||
/* LOG_REGION_LINKLAYER */
|
||||
#if (CFG_LOG_SUPPORTED != 0)
|
||||
#define LOG_INFO_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_LINKLAYER, __VA_ARGS__)
|
||||
#define LOG_ERROR_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_LINKLAYER, __VA_ARGS__)
|
||||
#define LOG_WARNING_LINKLAYER(...)Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_LINKLAYER, __VA_ARGS__)
|
||||
#define LOG_DEBUG_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_LINKLAYER, __VA_ARGS__)
|
||||
#else /* (CFG_LOG_SUPPORTED != 0) */
|
||||
#define LOG_INFO_LINKLAYER(...) do {} while(0)
|
||||
#define LOG_ERROR_LINKLAYER(...) do {} while(0)
|
||||
#define LOG_WARNING_LINKLAYER(...)do {} while(0)
|
||||
#define LOG_DEBUG_LINKLAYER(...) do {} while(0)
|
||||
#endif /* (CFG_LOG_SUPPORTED != 0) */
|
||||
|
||||
/* USER CODE BEGIN LOG_REGION_LINKLAYER */
|
||||
/**
|
||||
* Add inside this user section your defines to match the new verbose levels you
|
||||
* created into Log_Verbose_Level_t.
|
||||
* Example :
|
||||
* #define LOG_CUSTOM_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_LINKLAYER, __VA_ARGS__);
|
||||
*
|
||||
* You don't need to update all regions with your custom values.
|
||||
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
|
||||
*/
|
||||
|
||||
/* USER CODE END LOG_REGION_LINKLAYER */
|
||||
|
||||
/* USER CODE BEGIN APP_LOG_USER_DEFINES */
|
||||
/**
|
||||
* Add inside this user section your defines to match the new regions you
|
||||
* created into Log_Region_t.
|
||||
* Example :
|
||||
#if (CFG_LOG_SUPPORTED != 0)
|
||||
#define LOG_INFO_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_CUSTOM, __VA_ARGS__)
|
||||
#define LOG_ERROR_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_CUSTOM, __VA_ARGS__)
|
||||
#define LOG_WARNING_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_CUSTOM, __VA_ARGS__)
|
||||
#define LOG_DEBUG_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_CUSTOM, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_INFO_CUSTOM(...) do {} while(0)
|
||||
#define LOG_ERROR_CUSTOM(...) do {} while(0)
|
||||
#define LOG_WARNING_CUSTOM(...) do {} while(0)
|
||||
#define LOG_DEBUG_CUSTOM(...) do {} while(0)
|
||||
#endif
|
||||
*/
|
||||
/* USER CODE END APP_LOG_USER_DEFINES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LOG_MODULE_CONF_H */
|
||||
@@ -0,0 +1,716 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file advanced_memory_manager.c
|
||||
* @author MCD Application Team
|
||||
* @brief Memory Manager
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm_list.h"
|
||||
#include "utilities_conf.h"
|
||||
#include "advanced_memory_manager.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
|
||||
/* Defines that the module is not initialized */
|
||||
#define NOT_INITIALIZED 0x00u
|
||||
/* Defines that the module is initialized */
|
||||
#define INITIALIZED 0x01u
|
||||
|
||||
/* Defines the bit to check for 32bits aligned values */
|
||||
#define MASK_ALIGNED_32BITS 0x03u
|
||||
|
||||
/*
|
||||
Defines the length of the Virtual Memory Header in 32bits
|
||||
----------------------------------------
|
||||
| +++ 8bits +++ | +++++++ 24bits +++++++ |
|
||||
| VirtualMem ID | Buffer Size (n*32bits) |
|
||||
----------------------------------------
|
||||
*/
|
||||
#define VIRTUAL_MEMORY_HEADER_SIZE 0x01
|
||||
|
||||
/* Position of the ID field in Virtual Memory Header */
|
||||
#define VIRTUAL_MEMORY_HEADER_ID_POS 0x18
|
||||
/* Mask of the ID field in Virtual Memory Header */
|
||||
#define VIRTUAL_MEMORY_HEADER_ID_MASK 0xFF000000
|
||||
|
||||
/* Position of the Buffer Size field in Virtual Memory Header */
|
||||
#define VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS 0x00
|
||||
/* Mask of the Buffer Size field in Virtual Memory Header */
|
||||
#define VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK 0x00FFFFFF
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* AMM Initialized flag */
|
||||
static uint8_t AmmInitialized = NOT_INITIALIZED;
|
||||
|
||||
/* AMM pool address */
|
||||
static uint32_t * p_AmmPoolAddress;
|
||||
|
||||
/* AMM pool size */
|
||||
static uint32_t AmmPoolSize;
|
||||
|
||||
/* AMM occupied shared pool size */
|
||||
static uint32_t AmmOccupiedSharedPoolSize;
|
||||
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
/* AMM peak shared pool size */
|
||||
static uint32_t AmmPeakSharedPoolSize;
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
/* AMM needed virtual memory */
|
||||
static uint32_t AmmRequiredVirtualMemorySize;
|
||||
|
||||
/* AMM virtual memory number */
|
||||
static uint32_t AmmVirtualMemoryNumber;
|
||||
|
||||
/* List of Virtual Memories info */
|
||||
static VirtualMemoryInfo_t * p_AmmVirtualMemoryList;
|
||||
|
||||
/* Handler of the Basic Memory Manager functions */
|
||||
static AMM_BasicMemoryManagerFunctions_t AmmBmmFunctionsHandler;
|
||||
|
||||
/* Pointer on the first element of the pending callbacks */
|
||||
static AMM_VirtualMemoryCallbackHeader_t AmmPendingCallback;
|
||||
|
||||
/* Pointer on the first element of the active callbacks */
|
||||
static AMM_VirtualMemoryCallbackHeader_t AmmActiveCallback;
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Push a callback structure into the Pending FIFO
|
||||
* @param p_CallbackElt: Pointer onto the callback to push
|
||||
* @return None
|
||||
*/
|
||||
static inline void pushPending (AMM_VirtualMemoryCallbackFunction_t * const p_CallbackElt);
|
||||
|
||||
/**
|
||||
* @brief Push the Pending callback(s) into the Active FIFO
|
||||
* @return None
|
||||
*/
|
||||
static inline void passPendingToActive (void);
|
||||
|
||||
/**
|
||||
* @brief Pop a callback structure from the Active FIFO
|
||||
* @return Pointer onto the popped callback
|
||||
*/
|
||||
static inline AMM_VirtualMemoryCallbackFunction_t * popActive (void);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
uint32_t GetCurrentOccupation (const uint8_t VirtualMemoryId)
|
||||
{
|
||||
uint32_t currentOccupation = 0x00;
|
||||
|
||||
if (AmmInitialized == INITIALIZED)
|
||||
{
|
||||
/* Shared memory use case */
|
||||
if (VirtualMemoryId == AMM_NO_VIRTUAL_ID)
|
||||
{
|
||||
currentOccupation = AmmOccupiedSharedPoolSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check virtual memory info */
|
||||
for (uint32_t memIdx = 0x00;
|
||||
(memIdx < AmmVirtualMemoryNumber) && (currentOccupation == 0x00);
|
||||
memIdx++)
|
||||
{
|
||||
/* Check if ID is known */
|
||||
if (VirtualMemoryId == p_AmmVirtualMemoryList[memIdx].Id)
|
||||
{
|
||||
currentOccupation = p_AmmVirtualMemoryList[memIdx].OccupiedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentOccupation;
|
||||
}
|
||||
|
||||
uint32_t GetPeakOccupation (const uint8_t VirtualMemoryId)
|
||||
{
|
||||
uint32_t peakOccupation = 0x00;
|
||||
|
||||
if (AmmInitialized == INITIALIZED)
|
||||
{
|
||||
/* Shared memory use case */
|
||||
if (VirtualMemoryId == AMM_NO_VIRTUAL_ID)
|
||||
{
|
||||
peakOccupation = AmmPeakSharedPoolSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check virtual memory info */
|
||||
for (uint32_t memIdx = 0x00;
|
||||
(memIdx < AmmVirtualMemoryNumber) && (peakOccupation == 0x00);
|
||||
memIdx++)
|
||||
{
|
||||
/* Check if ID is known */
|
||||
if (VirtualMemoryId == p_AmmVirtualMemoryList[memIdx].Id)
|
||||
{
|
||||
peakOccupation = p_AmmVirtualMemoryList[memIdx].PeakOccupationSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return peakOccupation;
|
||||
}
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
AMM_Function_Error_t AMM_Init (const AMM_InitParameters_t * const p_InitParams)
|
||||
{
|
||||
AMM_Function_Error_t error = AMM_ERROR_NOK;
|
||||
|
||||
uint32_t neededPoolSize = 0x00;
|
||||
|
||||
/* Check if not already initialized */
|
||||
if (AmmInitialized == INITIALIZED)
|
||||
{
|
||||
error = AMM_ERROR_ALREADY_INIT;
|
||||
}
|
||||
/* Check parameter null pointer */
|
||||
else if (p_InitParams == NULL)
|
||||
{
|
||||
error = AMM_ERROR_BAD_POINTER;
|
||||
}
|
||||
/* Check Pool address null pointer */
|
||||
else if (p_InitParams->p_PoolAddr == NULL)
|
||||
{
|
||||
error = AMM_ERROR_BAD_POOL_CONFIG;
|
||||
}
|
||||
/* Check if Pool address is 32bits aligned */
|
||||
else if ((MASK_ALIGNED_32BITS & (uint32_t)p_InitParams->p_PoolAddr) != 0)
|
||||
{
|
||||
error = AMM_ERROR_BAD_POOL_CONFIG;
|
||||
}
|
||||
/* Check Pool size shall be non zero */
|
||||
else if (p_InitParams->PoolSize == 0)
|
||||
{
|
||||
error = AMM_ERROR_BAD_POOL_CONFIG;
|
||||
}
|
||||
/* Check that Virtual memories can not be declared without a proper configuration list */
|
||||
else if ((p_InitParams->VirtualMemoryNumber != 0x00) &&
|
||||
(p_InitParams->p_VirtualMemoryConfigList == NULL))
|
||||
{
|
||||
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
|
||||
}
|
||||
else
|
||||
{
|
||||
neededPoolSize = p_InitParams->VirtualMemoryNumber * AMM_VIRTUAL_INFO_ELEMENT_SIZE;
|
||||
|
||||
/* Check the parameters relative to virtual memories */
|
||||
for (uint32_t memIdx = 0x00;
|
||||
(memIdx < p_InitParams->VirtualMemoryNumber) && (error == AMM_ERROR_NOK);
|
||||
memIdx++)
|
||||
{
|
||||
/* Add the amount of needed space for this virtual memory */
|
||||
neededPoolSize = neededPoolSize + p_InitParams->p_VirtualMemoryConfigList[memIdx].BufferSize;
|
||||
|
||||
/* Check the virtual memory ID. Shall not be zero */
|
||||
if (p_InitParams->p_VirtualMemoryConfigList[memIdx].Id == 0)
|
||||
{
|
||||
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
|
||||
}
|
||||
/* Check if size is not zero */
|
||||
else if (p_InitParams->p_VirtualMemoryConfigList[memIdx].BufferSize == 0)
|
||||
{
|
||||
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
|
||||
}
|
||||
/* Check if amount of needed memory has overlapped current pool size */
|
||||
else if (p_InitParams->PoolSize < neededPoolSize)
|
||||
{
|
||||
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing, all ok yet */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if parameters are still ok */
|
||||
if (error == AMM_ERROR_NOK)
|
||||
{
|
||||
/* Init all private variables: Pool relative */
|
||||
p_AmmPoolAddress = NULL;
|
||||
AmmPoolSize = 0x00;
|
||||
AmmOccupiedSharedPoolSize = 0x00;
|
||||
AmmRequiredVirtualMemorySize = 0x00;
|
||||
|
||||
/* Init all private variables: Virtual Memory relative */
|
||||
AmmVirtualMemoryNumber = 0x00;
|
||||
p_AmmVirtualMemoryList = NULL;
|
||||
|
||||
/* Init all private variables: BMM relative */
|
||||
AmmBmmFunctionsHandler.Init = NULL;
|
||||
AmmBmmFunctionsHandler.Allocate = NULL;
|
||||
AmmBmmFunctionsHandler.Free = NULL;
|
||||
|
||||
/* Init all private variables: Callbacks relative */
|
||||
AmmPendingCallback.next = NULL;
|
||||
AmmPendingCallback.prev = NULL;
|
||||
AmmActiveCallback.next = NULL;
|
||||
AmmActiveCallback.prev = NULL;
|
||||
|
||||
/* First get the Basic Memory Manager functions back */
|
||||
AMM_RegisterBasicMemoryManager (&AmmBmmFunctionsHandler);
|
||||
|
||||
if ((AmmBmmFunctionsHandler.Init == NULL)
|
||||
|| (AmmBmmFunctionsHandler.Allocate == NULL)
|
||||
|| (AmmBmmFunctionsHandler.Free == NULL))
|
||||
{
|
||||
error = AMM_ERROR_BAD_BMM_REGISTRATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Store the pool info */
|
||||
p_AmmPoolAddress = p_InitParams->p_PoolAddr;
|
||||
AmmPoolSize = p_InitParams->PoolSize;
|
||||
|
||||
/* First init the Basic Memory Manager */
|
||||
AmmBmmFunctionsHandler.Init (p_AmmPoolAddress,
|
||||
AmmPoolSize);
|
||||
|
||||
/* Allocate memory for the virtual memories info */
|
||||
p_AmmVirtualMemoryList = (VirtualMemoryInfo_t *)
|
||||
(AmmBmmFunctionsHandler. Allocate (AMM_VIRTUAL_INFO_ELEMENT_SIZE
|
||||
* p_InitParams->VirtualMemoryNumber));
|
||||
|
||||
/* Check if allocation is OK*/
|
||||
if ((p_AmmVirtualMemoryList == NULL) && (p_InitParams->VirtualMemoryNumber > 0))
|
||||
{
|
||||
error = AMM_ERROR_BAD_BMM_ALLOCATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Init Critical section */
|
||||
UTIL_SEQ_INIT_CRITICAL_SECTION ();
|
||||
|
||||
/* Init both pending and active list */
|
||||
LST_init_head (&AmmPendingCallback);
|
||||
LST_init_head (&AmmActiveCallback);
|
||||
|
||||
/* Keep going on init, fulfill the virtual memories info */
|
||||
AmmVirtualMemoryNumber = p_InitParams->VirtualMemoryNumber;
|
||||
|
||||
/* Actualize actual shared pool occupied size */
|
||||
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize + (AMM_VIRTUAL_INFO_ELEMENT_SIZE
|
||||
* AmmVirtualMemoryNumber);
|
||||
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
AmmPeakSharedPoolSize = AmmOccupiedSharedPoolSize;
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
for (uint32_t memIdx = 0x00;
|
||||
memIdx < AmmVirtualMemoryNumber;
|
||||
memIdx++)
|
||||
{
|
||||
p_AmmVirtualMemoryList[memIdx].Id = p_InitParams->p_VirtualMemoryConfigList[memIdx].Id;
|
||||
p_AmmVirtualMemoryList[memIdx].RequiredSize = p_InitParams->p_VirtualMemoryConfigList[memIdx].BufferSize;
|
||||
p_AmmVirtualMemoryList[memIdx].OccupiedSize = 0x00;
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
p_AmmVirtualMemoryList[memIdx].PeakOccupationSize = 0x00;
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
AmmRequiredVirtualMemorySize = AmmRequiredVirtualMemorySize + p_AmmVirtualMemoryList[memIdx].RequiredSize;
|
||||
}
|
||||
|
||||
/* Set init flag */
|
||||
AmmInitialized = INITIALIZED;
|
||||
|
||||
/* All info are stored and AMM is initialized */
|
||||
error = AMM_ERROR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
AMM_Function_Error_t AMM_DeInit (void)
|
||||
{
|
||||
AMM_Function_Error_t error = AMM_ERROR_NOK;
|
||||
|
||||
/* Check if initialized */
|
||||
if (AmmInitialized == INITIALIZED)
|
||||
{
|
||||
/* Free resources */
|
||||
AmmBmmFunctionsHandler.Free ((uint32_t *)p_AmmVirtualMemoryList);
|
||||
|
||||
/* Reset all the variables */
|
||||
AmmBmmFunctionsHandler.Init = NULL;
|
||||
AmmBmmFunctionsHandler.Allocate = NULL;
|
||||
AmmBmmFunctionsHandler.Free = NULL;
|
||||
|
||||
p_AmmPoolAddress = 0x00;
|
||||
AmmPoolSize = 0x00;
|
||||
AmmOccupiedSharedPoolSize = 0x00;
|
||||
AmmRequiredVirtualMemorySize = 0x00;
|
||||
AmmVirtualMemoryNumber = 0x00;
|
||||
|
||||
/* Unset the flag */
|
||||
AmmInitialized = 0x00;
|
||||
|
||||
error = AMM_ERROR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = AMM_ERROR_NOT_INIT;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
AMM_Function_Error_t AMM_Alloc (const uint8_t VirtualMemoryId,
|
||||
const uint32_t BufferSize,
|
||||
uint32_t ** pp_AllocBuffer,
|
||||
AMM_VirtualMemoryCallbackFunction_t * const p_CallBackFunction)
|
||||
{
|
||||
AMM_Function_Error_t error = AMM_ERROR_NOK;
|
||||
|
||||
uint32_t selfAvailable = 0x00;
|
||||
|
||||
uint32_t * p_TmpAllocAddr = NULL;
|
||||
|
||||
/* Set pointer to NULL */
|
||||
*pp_AllocBuffer = NULL;
|
||||
|
||||
if (AmmInitialized == NOT_INITIALIZED)
|
||||
{
|
||||
error = AMM_ERROR_NOT_INIT;
|
||||
}
|
||||
/* Check if buffer size is not zero */
|
||||
else if (BufferSize == 0)
|
||||
{
|
||||
error = AMM_ERROR_BAD_ALLOCATION_SIZE;
|
||||
}
|
||||
/* Check if no virtual ID requested */
|
||||
else if (VirtualMemoryId == AMM_NO_VIRTUAL_ID)
|
||||
{
|
||||
/* Enter critical section */
|
||||
UTIL_SEQ_ENTER_CRITICAL_SECTION ();
|
||||
|
||||
/* Check for enough space in the shared pool */
|
||||
if (BufferSize < (AmmPoolSize - AmmOccupiedSharedPoolSize - AmmRequiredVirtualMemorySize))
|
||||
{
|
||||
/* Try Allocation. Do not forget the header */
|
||||
p_TmpAllocAddr = AmmBmmFunctionsHandler.Allocate (BufferSize + VIRTUAL_MEMORY_HEADER_SIZE);
|
||||
|
||||
/* Check if allocation is OK */
|
||||
if (p_TmpAllocAddr != NULL)
|
||||
{
|
||||
/* Fulfill the header */
|
||||
*p_TmpAllocAddr = (uint32_t)(((uint32_t)VirtualMemoryId << VIRTUAL_MEMORY_HEADER_ID_POS)
|
||||
& VIRTUAL_MEMORY_HEADER_ID_MASK)
|
||||
| ((BufferSize << VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS)
|
||||
& VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK);
|
||||
|
||||
/* Provide the right address to user, ie without the header */
|
||||
*pp_AllocBuffer = (uint32_t *)(p_TmpAllocAddr + VIRTUAL_MEMORY_HEADER_SIZE);
|
||||
|
||||
/* Actualize the current memory occupation of the shared space */
|
||||
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize + BufferSize + VIRTUAL_MEMORY_HEADER_SIZE;
|
||||
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
/* Check if peak occupation has to be updated */
|
||||
if (AmmOccupiedSharedPoolSize > AmmPeakSharedPoolSize)
|
||||
{
|
||||
AmmPeakSharedPoolSize = AmmOccupiedSharedPoolSize;
|
||||
}
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
error = AMM_ERROR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Register the callback for a future retry */
|
||||
pushPending (p_CallBackFunction);
|
||||
|
||||
error = AMM_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Register the callback for a future retry */
|
||||
pushPending (p_CallBackFunction);
|
||||
|
||||
error = AMM_ERROR_BAD_ALLOCATION_SIZE;
|
||||
}
|
||||
|
||||
/* Exit critical section */
|
||||
UTIL_SEQ_EXIT_CRITICAL_SECTION ();
|
||||
}
|
||||
/* A specific ID is requested */
|
||||
else
|
||||
{
|
||||
error = AMM_ERROR_UNKNOWN_ID;
|
||||
|
||||
/* Enter critical section */
|
||||
UTIL_SEQ_ENTER_CRITICAL_SECTION ();
|
||||
|
||||
/* Check virtual memory info */
|
||||
for (uint32_t memIdx = 0x00;
|
||||
(memIdx < AmmVirtualMemoryNumber) && (error == AMM_ERROR_UNKNOWN_ID);
|
||||
memIdx++)
|
||||
{
|
||||
/* Check if ID is known */
|
||||
if (VirtualMemoryId == p_AmmVirtualMemoryList[memIdx].Id)
|
||||
{
|
||||
/* Check if all the reserved memory has been consumed */
|
||||
if (p_AmmVirtualMemoryList[memIdx].OccupiedSize < p_AmmVirtualMemoryList[memIdx].RequiredSize)
|
||||
{
|
||||
/* Compute what is remaining */
|
||||
selfAvailable = p_AmmVirtualMemoryList[memIdx].RequiredSize
|
||||
- p_AmmVirtualMemoryList[memIdx].OccupiedSize;
|
||||
}
|
||||
|
||||
/* Check if there is enough space in the shared pool plus in our virtual memory pool */
|
||||
if (BufferSize < (AmmPoolSize - AmmOccupiedSharedPoolSize - AmmRequiredVirtualMemorySize + selfAvailable))
|
||||
{
|
||||
/* Try Allocation. Do not forget the header */
|
||||
p_TmpAllocAddr = AmmBmmFunctionsHandler.Allocate ((BufferSize + VIRTUAL_MEMORY_HEADER_SIZE));
|
||||
|
||||
/* Check if allocation is OK */
|
||||
if (p_TmpAllocAddr != NULL)
|
||||
{
|
||||
/* Fulfill the header */
|
||||
*p_TmpAllocAddr = (uint32_t)(((uint32_t)VirtualMemoryId << VIRTUAL_MEMORY_HEADER_ID_POS)
|
||||
& VIRTUAL_MEMORY_HEADER_ID_MASK)
|
||||
| ((BufferSize << VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS)
|
||||
& VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK);
|
||||
|
||||
/* Provide the right address to user, ie without the header */
|
||||
*pp_AllocBuffer = (uint32_t *)(p_TmpAllocAddr + VIRTUAL_MEMORY_HEADER_SIZE);
|
||||
|
||||
/* Actualize our current memory occupation */
|
||||
p_AmmVirtualMemoryList[memIdx].OccupiedSize = p_AmmVirtualMemoryList[memIdx].OccupiedSize
|
||||
+ BufferSize
|
||||
+ VIRTUAL_MEMORY_HEADER_SIZE;
|
||||
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
/* Check if peak occupation has to be updated */
|
||||
if (p_AmmVirtualMemoryList[memIdx].OccupiedSize > p_AmmVirtualMemoryList[memIdx].PeakOccupationSize)
|
||||
{
|
||||
p_AmmVirtualMemoryList[memIdx].PeakOccupationSize = p_AmmVirtualMemoryList[memIdx].OccupiedSize;
|
||||
}
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
/* Check for overlapping the reserved memory */
|
||||
if (p_AmmVirtualMemoryList[memIdx].RequiredSize < p_AmmVirtualMemoryList[memIdx].OccupiedSize)
|
||||
{
|
||||
/* Actualize the shared memory occupation */
|
||||
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize
|
||||
+ BufferSize - selfAvailable
|
||||
+ VIRTUAL_MEMORY_HEADER_SIZE;
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
/* Check if peak occupation has to be updated */
|
||||
if (AmmOccupiedSharedPoolSize > AmmPeakSharedPoolSize)
|
||||
{
|
||||
AmmPeakSharedPoolSize = AmmOccupiedSharedPoolSize;
|
||||
}
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
}
|
||||
|
||||
error = AMM_ERROR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Register the callback for a future retry */
|
||||
pushPending (p_CallBackFunction);
|
||||
|
||||
error = AMM_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Register the callback for a future retry */
|
||||
pushPending (p_CallBackFunction);
|
||||
|
||||
error = AMM_ERROR_BAD_ALLOCATION_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Exit critical section */
|
||||
UTIL_SEQ_EXIT_CRITICAL_SECTION ();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
AMM_Function_Error_t AMM_Free (uint32_t * const p_BufferAddr)
|
||||
{
|
||||
AMM_Function_Error_t error = AMM_ERROR_NOK;
|
||||
|
||||
uint8_t virtualId = 0x00;
|
||||
int32_t occupiedOverRequired = 0x00;
|
||||
uint32_t allocatedSize = 0x00;
|
||||
|
||||
uint32_t * p_TmpAllocAddr = NULL;
|
||||
|
||||
if (AmmInitialized == NOT_INITIALIZED)
|
||||
{
|
||||
error = AMM_ERROR_NOT_INIT;
|
||||
}
|
||||
else if (p_BufferAddr == NULL)
|
||||
{
|
||||
error = AMM_ERROR_BAD_POINTER;
|
||||
}
|
||||
else if ((MASK_ALIGNED_32BITS & (uint32_t)p_BufferAddr) != 0)
|
||||
{
|
||||
error = AMM_ERROR_NOT_ALIGNED;
|
||||
}
|
||||
/* Check if address is managed by this AMM */
|
||||
else if ((p_BufferAddr > (p_AmmPoolAddress + AmmPoolSize))
|
||||
|| (p_BufferAddr < p_AmmPoolAddress))
|
||||
{
|
||||
error = AMM_ERROR_OUT_OF_RANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enter critical section */
|
||||
UTIL_SEQ_ENTER_CRITICAL_SECTION ();
|
||||
|
||||
/* First correct the address by adding the header */
|
||||
p_TmpAllocAddr = (uint32_t *)(p_BufferAddr - VIRTUAL_MEMORY_HEADER_SIZE);
|
||||
|
||||
/* Get the virtual memory information */
|
||||
virtualId = (*p_TmpAllocAddr & VIRTUAL_MEMORY_HEADER_ID_MASK) >> VIRTUAL_MEMORY_HEADER_ID_POS;
|
||||
allocatedSize = (*p_TmpAllocAddr & VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK) >> VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS;
|
||||
|
||||
/* Add header size to allocated size */
|
||||
allocatedSize = allocatedSize + VIRTUAL_MEMORY_HEADER_SIZE;
|
||||
|
||||
/* Free the allocated memory */
|
||||
AmmBmmFunctionsHandler.Free(p_TmpAllocAddr);
|
||||
|
||||
/* Update the occupation counters depending on the ID */
|
||||
if (virtualId == AMM_NO_VIRTUAL_ID)
|
||||
{
|
||||
/* Update the occupation size */
|
||||
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize - allocatedSize;
|
||||
|
||||
error = AMM_ERROR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = AMM_ERROR_UNKNOWN_ID;
|
||||
|
||||
for (uint32_t memIdx = 0x00;
|
||||
(memIdx < AmmVirtualMemoryNumber) && (error == AMM_ERROR_UNKNOWN_ID);
|
||||
memIdx++)
|
||||
{
|
||||
/* Check if it is the right ID */
|
||||
if (virtualId == p_AmmVirtualMemoryList[memIdx].Id)
|
||||
{
|
||||
occupiedOverRequired = (p_AmmVirtualMemoryList[memIdx].OccupiedSize - p_AmmVirtualMemoryList[memIdx].RequiredSize);
|
||||
|
||||
/* Check whether the occupied size has overlaped the required or not */
|
||||
if (occupiedOverRequired > 0x00)
|
||||
{
|
||||
/* Check if reserved memory is overlapped */
|
||||
if (allocatedSize > occupiedOverRequired)
|
||||
{
|
||||
/* Update the occupation size */
|
||||
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize
|
||||
- (p_AmmVirtualMemoryList[memIdx].OccupiedSize
|
||||
- p_AmmVirtualMemoryList[memIdx].RequiredSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize - allocatedSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the occupation size */
|
||||
p_AmmVirtualMemoryList[memIdx].OccupiedSize = p_AmmVirtualMemoryList[memIdx].OccupiedSize
|
||||
- allocatedSize;
|
||||
|
||||
error = AMM_ERROR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop pending callbacks and add them to the active fifo */
|
||||
passPendingToActive ();
|
||||
|
||||
/* Exit critical section */
|
||||
UTIL_SEQ_EXIT_CRITICAL_SECTION ();
|
||||
|
||||
/* Ask the user task to proceed to a background process call */
|
||||
AMM_ProcessRequest();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void AMM_BackgroundProcess (void)
|
||||
{
|
||||
AMM_VirtualMemoryCallbackFunction_t * p_tmpCallback = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
/* Pop an active callback request */
|
||||
p_tmpCallback = popActive();
|
||||
|
||||
if (p_tmpCallback != NULL)
|
||||
{
|
||||
/* Invoke the callback for an alloc retry */
|
||||
p_tmpCallback->Callback();
|
||||
}
|
||||
}while (p_tmpCallback != NULL);
|
||||
}
|
||||
|
||||
/* Private Functions Definition ------------------------------------------------------*/
|
||||
|
||||
void pushPending (AMM_VirtualMemoryCallbackFunction_t * const p_CallbackElt)
|
||||
{
|
||||
if (p_CallbackElt != NULL)
|
||||
{
|
||||
/* Add the new callback */
|
||||
LST_insert_tail (&AmmPendingCallback, (tListNode *)p_CallbackElt);
|
||||
}
|
||||
}
|
||||
|
||||
void passPendingToActive (void)
|
||||
{
|
||||
AMM_VirtualMemoryCallbackFunction_t * p_TmpElt = NULL;
|
||||
|
||||
while (LST_is_empty (&AmmPendingCallback) == FALSE)
|
||||
{
|
||||
/* Remove the head element */
|
||||
LST_remove_head (&AmmPendingCallback, (tListNode**)&p_TmpElt);
|
||||
/* Add at the bottom */
|
||||
LST_insert_tail (&AmmActiveCallback, (tListNode *)p_TmpElt);
|
||||
}
|
||||
}
|
||||
|
||||
AMM_VirtualMemoryCallbackFunction_t * popActive (void)
|
||||
{
|
||||
AMM_VirtualMemoryCallbackFunction_t * p_error = NULL;
|
||||
|
||||
if (LST_is_empty (&AmmActiveCallback) == FALSE)
|
||||
{
|
||||
/* Remove last element */
|
||||
LST_remove_head (&AmmActiveCallback, (tListNode**)&p_error);
|
||||
}
|
||||
|
||||
return p_error;
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file advance_memory_manager.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for advance_memory_manager.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef ADVANCED_MEMORY_MANAGER_H
|
||||
#define ADVANCED_MEMORY_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm_list.h"
|
||||
|
||||
/* Exported defines -----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Define for No Virtual Memory ID
|
||||
*
|
||||
* @details This ID can be used to allocate memory from the shared pool
|
||||
*/
|
||||
#define AMM_NO_VIRTUAL_ID 0x00u
|
||||
|
||||
/**
|
||||
* @brief Size of a virtual memory information element in 32bits
|
||||
*
|
||||
* @details At initialization, the Advance Memory Manager allocate as many VM info element as there
|
||||
* is Virtual Memory to manage.
|
||||
* Thus user shall provide at the initialization more space for the pool.
|
||||
*
|
||||
* ie:
|
||||
* - sizeOfDesiredPool = 8092
|
||||
* - numberOfVirtualMemory = 3
|
||||
* - actualSizeOfThePoolToGive = sizeOfDesiredPool + numberOfVirtualMemory * AMM_VIRTUAL_INFO_ELEMENT_SIZE
|
||||
*/
|
||||
#define AMM_VIRTUAL_INFO_ELEMENT_SIZE (uint32_t)(sizeof (VirtualMemoryInfo_t) / sizeof (uint32_t))
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Redefine the header for chained list */
|
||||
typedef tListNode AMM_VirtualMemoryCallbackHeader_t;
|
||||
|
||||
/* Function error enumeration */
|
||||
typedef enum AMM_Function_Error
|
||||
{
|
||||
/* No error code */
|
||||
AMM_ERROR_OK,
|
||||
/* Error that occurred before any check */
|
||||
AMM_ERROR_NOK,
|
||||
/*Bad pointer error */
|
||||
AMM_ERROR_BAD_POINTER,
|
||||
/* Bad pool configuration error */
|
||||
AMM_ERROR_BAD_POOL_CONFIG,
|
||||
/* Bad virtual memory configuration error */
|
||||
AMM_ERROR_BAD_VIRTUAL_CONFIG,
|
||||
/* Bad BMM registration error */
|
||||
AMM_ERROR_BAD_BMM_REGISTRATION,
|
||||
/* Bad BMM allocation error */
|
||||
AMM_ERROR_BAD_BMM_ALLOCATION,
|
||||
/* Not aligned address error */
|
||||
AMM_ERROR_NOT_ALIGNED,
|
||||
/* Out of range error */
|
||||
AMM_ERROR_OUT_OF_RANGE,
|
||||
/* Unknown virtual memory manager ID error */
|
||||
AMM_ERROR_UNKNOWN_ID,
|
||||
/* Bad allocation size error */
|
||||
AMM_ERROR_BAD_ALLOCATION_SIZE,
|
||||
/* Allocation failed error */
|
||||
AMM_ERROR_ALLOCATION_FAILED,
|
||||
/* Already initialized AMM error */
|
||||
AMM_ERROR_ALREADY_INIT,
|
||||
/* Not initialized AMM error */
|
||||
AMM_ERROR_NOT_INIT
|
||||
} AMM_Function_Error_t;
|
||||
|
||||
/**
|
||||
* @brief Virtual Memory information struct
|
||||
*/
|
||||
typedef struct __attribute__((packed, aligned(4))) VirtualMemoryInfo
|
||||
{
|
||||
/* Identifier of the Virtual Memory */
|
||||
uint8_t Id;
|
||||
/* Size required for this Virtual Memory buffer with a multiple of 32bits */
|
||||
uint32_t RequiredSize;
|
||||
/* Current occupation of the Virtual Memory buffer with a multiple of 32bits */
|
||||
uint32_t OccupiedSize;
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
/* Peak occupation of the Virtual Memory buffer with a multiple of 32bits */
|
||||
uint32_t PeakOccupationSize;
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
}VirtualMemoryInfo_t;
|
||||
|
||||
/**
|
||||
* @brief Virtual Memory configuration struct
|
||||
*/
|
||||
typedef struct AMM_VirtualMemoryConfig
|
||||
{
|
||||
/* ID of the Virtual Memory */
|
||||
uint8_t Id;
|
||||
/* Size of the Virtual Memory buffer with a multiple of 32bits.
|
||||
|
||||
ie: BufferSize = 4; TotalSize = BufferSize * 32bits
|
||||
= 4 * 32bits
|
||||
= 128 bits */
|
||||
uint32_t BufferSize;
|
||||
}AMM_VirtualMemoryConfig_t;
|
||||
|
||||
/**
|
||||
* @brief Basic Memory Manager functions struct
|
||||
*
|
||||
* @details Structure that handles all the required functions of the Basic Memory Manager.
|
||||
*/
|
||||
typedef struct AMM_BasicMemoryManagerFunctions
|
||||
{
|
||||
/* Basic Memory Manager Init function - Shall be in bytes - */
|
||||
void (* Init) (uint32_t * const p_PoolAddr, const uint32_t PoolSize);
|
||||
/* Basic Memory Manager Allocate function - Shall be in bytes - */
|
||||
uint32_t * (* Allocate) (const uint32_t BufferSize);
|
||||
/* Basic Memory Manager Free function */
|
||||
void (* Free) (uint32_t * const p_BufferAddr);
|
||||
}AMM_BasicMemoryManagerFunctions_t;
|
||||
|
||||
/**
|
||||
* @brief Advance Memory Manager init struct
|
||||
*
|
||||
* @details Structure that contains all the needed parameters to initialize the
|
||||
* Advance Memory Manager.
|
||||
*/
|
||||
typedef struct AMM_InitParameters
|
||||
{
|
||||
/* Address of the pool of memory to manage */
|
||||
uint32_t * p_PoolAddr;
|
||||
/* Size of the pool with a multiple of 32bits.
|
||||
|
||||
ie: PoolSize = 4; TotalSize = PoolSize * 32bits
|
||||
= 4 * 32bits
|
||||
= 128 bits */
|
||||
uint32_t PoolSize;
|
||||
/* Number of Virtual Memory to create */
|
||||
uint32_t VirtualMemoryNumber;
|
||||
/* List of the Virtual Memory configurations */
|
||||
AMM_VirtualMemoryConfig_t * p_VirtualMemoryConfigList;
|
||||
}AMM_InitParameters_t;
|
||||
|
||||
/**
|
||||
* @brief Virtual Memory Callback function struct
|
||||
*/
|
||||
typedef struct AMM_VirtualMemoryCallbackFunction
|
||||
{
|
||||
/* Next and previous callbacks in the list */
|
||||
AMM_VirtualMemoryCallbackHeader_t Header;
|
||||
/* Callback function pointer to invoke once memory has been freed */
|
||||
void (* Callback) (void);
|
||||
}AMM_VirtualMemoryCallbackFunction_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
|
||||
#if (AMM_USE_MEMORY_STATISTICS == 1)
|
||||
/**
|
||||
* @brief Get the Current Occupation of the required virtual memory
|
||||
* @details @ref AMM_NO_VIRTUAL_ID can be used to get the shared pool occupation
|
||||
* @param VirtualMemoryId: ID of the Virtual Memory
|
||||
* @return Value of the current occupation in 32bits words
|
||||
*/
|
||||
uint32_t GetCurrentOccupation (const uint8_t VirtualMemoryId);
|
||||
|
||||
/**
|
||||
* @brief Get the Peak Occupation of the required virtual memory
|
||||
* @details @ref AMM_NO_VIRTUAL_ID can be used to get the shared pool peak occupation
|
||||
* @param VirtualMemoryId: ID of the Virtual Memory
|
||||
* @return Value of the peak occupation in 32bits words
|
||||
*/
|
||||
uint32_t GetPeakOccupation (const uint8_t VirtualMemoryId);
|
||||
#endif /* AMM_USE_MEMORY_STATISTICS */
|
||||
|
||||
/**
|
||||
* @brief Initialize the Advance Memory Manager Pool
|
||||
* @param p_InitParams: Struct of init parameters
|
||||
* @return Status of the initialization
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_OK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_ALREADY_INIT
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POINTER
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POOL_CONFIG
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_VIRTUAL_CONFIG
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_BMM_REGISTRATION
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_BMM_ALLOCATION
|
||||
*/
|
||||
AMM_Function_Error_t AMM_Init (const AMM_InitParameters_t * const p_InitParams);
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the Advance Memory Manager Pool
|
||||
* @details This function shall be called once every allocated memory has been freed
|
||||
* @return Status of the initialization
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_OK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_INIT
|
||||
*/
|
||||
AMM_Function_Error_t AMM_DeInit (void);
|
||||
|
||||
/**
|
||||
* @brief Allocate a buffer from the Advance Memory Manager Pool
|
||||
* @param VirtualMemoryId: Virtual Memory Identifier - AMM_NO_VIRTUAL_ID Can be used -
|
||||
* @param BufferSize: Size of the pool with a multiple of 32bits.
|
||||
ie: BufferSize = 4; TotalSize = BufferSize * 32bits
|
||||
= 4 * 32bits
|
||||
= 128 bits
|
||||
* @param p_CallBackFunction: Pointer onto the Callback to call in case of failure - Can be NULL -
|
||||
* @param pp_AllocBuffer: Pointer onto the allocated buffer
|
||||
* @return Status of the allocation
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_OK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_INIT
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POINTER
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_UNKNOWN_ID
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_ALLOCATION_SIZE
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_ALLOCATION_FAILED
|
||||
*/
|
||||
AMM_Function_Error_t AMM_Alloc (const uint8_t VirtualMemoryId,
|
||||
const uint32_t BufferSize,
|
||||
uint32_t ** pp_AllocBuffer,
|
||||
AMM_VirtualMemoryCallbackFunction_t * const p_CallBackFunction);
|
||||
|
||||
/**
|
||||
* @brief Free the allocated buffer from the Advance Memory Manager Pool
|
||||
* @param p_BufferAddr: Address of the buffer to free
|
||||
* @return Status of the free
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_OK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_INIT
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POINTER
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_ALIGNED
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_OUT_OF_RANGE
|
||||
* @retval AMM_Function_Error_t::AMM_ERROR_UNKNOWN_ID
|
||||
*/
|
||||
AMM_Function_Error_t AMM_Free (uint32_t * const p_BufferAddr);
|
||||
|
||||
/**
|
||||
* @brief Background routine
|
||||
* @details Background routine that aims to call registered callbacks for an allocation retry
|
||||
* @return None
|
||||
*/
|
||||
void AMM_BackgroundProcess (void);
|
||||
|
||||
/* Exported functions to be implemented by the user if required ------------- */
|
||||
|
||||
/**
|
||||
* @brief Register the Basic Memory Manager functions to use
|
||||
* @param p_BasicMemoryManagerFunctions: Address of the basic memory manager functions
|
||||
* @return None
|
||||
*/
|
||||
void AMM_RegisterBasicMemoryManager (AMM_BasicMemoryManagerFunctions_t * const p_BasicMemoryManagerFunctions);
|
||||
|
||||
/**
|
||||
* @brief Request to application for a Background process run
|
||||
* @return None
|
||||
*/
|
||||
void AMM_ProcessRequest (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ADVANCED_MEMORY_MANAGER_H */
|
||||
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memory_manager.c
|
||||
* @author MCD Application Team
|
||||
* @brief Memory Manager
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2023 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
|
||||
#include "memory_manager.h"
|
||||
#include "stm_list.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/**
|
||||
* The average timing is @32Mhz :
|
||||
* Legacy MM
|
||||
* + Alloc = 3.5us
|
||||
* + Free = 2.5us
|
||||
* New MM
|
||||
* + Alloc = 6.5us
|
||||
* + Free = 4.5us
|
||||
*/
|
||||
#define USE_NEW_MM 1
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
#if(USE_NEW_MM == 0)
|
||||
#pragma default_variable_attributes = @"MM_CONTEXT"
|
||||
|
||||
static uint8_t QueueSize;
|
||||
static tListNode BufferPool;
|
||||
static MM_pCb_t BufferFreeCb;
|
||||
static uint8_t *p_StartPoolAdd;
|
||||
static uint8_t *p_EndPoolAdd;
|
||||
|
||||
#pragma default_variable_attributes =
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the Pools
|
||||
* @param p_pool: The pool of memory to manage
|
||||
* @param pool_size: The size of the pool
|
||||
* @param elt_size: The size of one element in the pool
|
||||
* @retval None
|
||||
*/
|
||||
void MM_Init(uint8_t *p_pool, uint32_t pool_size, uint32_t elt_size)
|
||||
{
|
||||
uint32_t elt_size_corrected;
|
||||
|
||||
QueueSize = 0;
|
||||
elt_size_corrected = 4*DIVC( elt_size, 4 );
|
||||
|
||||
/**
|
||||
* Save the first and last address of the pool of memory
|
||||
*/
|
||||
p_StartPoolAdd = p_pool;
|
||||
p_EndPoolAdd = p_pool + pool_size - 1;
|
||||
|
||||
/**
|
||||
* Initialize list
|
||||
*/
|
||||
LST_init_head (&BufferPool);
|
||||
|
||||
/**
|
||||
* Initialize the queue
|
||||
*/
|
||||
while(pool_size >= elt_size_corrected)
|
||||
{
|
||||
LST_insert_tail(&BufferPool, (tListNode *)p_pool);
|
||||
p_pool += elt_size_corrected;
|
||||
QueueSize++;
|
||||
pool_size -= elt_size_corrected;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide a buffer
|
||||
* @note The buffer allocated to the user shall be at least sizeof(tListNode) bytes
|
||||
* to store the memory manager chaining information
|
||||
*
|
||||
* @param size: The size of the buffer requested
|
||||
* @param cb: The callback to be called when a buffer is made available later on
|
||||
* if there is no buffer currently available when this API is called
|
||||
* @retval The buffer address when available or NULL when there is no buffer
|
||||
*/
|
||||
MM_pBufAdd_t MM_GetBuffer( uint32_t size, MM_pCb_t cb )
|
||||
{
|
||||
MM_pBufAdd_t buffer_address;
|
||||
uint32_t primask_bit;
|
||||
uint8_t allocation_exit = FALSE;
|
||||
|
||||
while( allocation_exit == FALSE )
|
||||
{
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
if ( QueueSize )
|
||||
{
|
||||
QueueSize--;
|
||||
LST_remove_head( &BufferPool, ( tListNode ** )&buffer_address );
|
||||
if((buffer_address >= p_StartPoolAdd) && (buffer_address <= (p_EndPoolAdd - size + 1)))
|
||||
{
|
||||
/* The buffer is in a valid range */
|
||||
BufferFreeCb = 0;
|
||||
allocation_exit = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* The buffer is not in a valid range.
|
||||
* Keep the reference out of the memory pool and try again
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferFreeCb = cb;
|
||||
buffer_address = 0;
|
||||
allocation_exit = TRUE;
|
||||
}
|
||||
__set_PRIMASK( primask_bit ); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
return buffer_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a buffer
|
||||
* @param p_buffer: The data buffer address
|
||||
* @retval None
|
||||
*/
|
||||
void MM_ReleaseBuffer( MM_pBufAdd_t p_buffer )
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
if((p_buffer >= p_StartPoolAdd) && (p_buffer <= p_EndPoolAdd))
|
||||
{
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
LST_insert_tail( &BufferPool, ( tListNode * )p_buffer );
|
||||
QueueSize++;
|
||||
__set_PRIMASK( primask_bit ); /**< Restore PRIMASK bit*/
|
||||
if( BufferFreeCb )
|
||||
{
|
||||
/**
|
||||
* The application is waiting for a free buffer
|
||||
*/
|
||||
BufferFreeCb();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#include "stm32_mm.h"
|
||||
|
||||
static uint8_t *p_StartPoolAdd __attribute__((section("MM_CONTEXT")));
|
||||
static uint8_t *p_EndPoolAdd __attribute__((section("MM_CONTEXT")));
|
||||
static MM_pCb_t BufferFreeCb __attribute__((section("MM_CONTEXT")));
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void MM_Init(uint8_t *p_pool, uint32_t pool_size, uint32_t elt_size)
|
||||
{
|
||||
/**
|
||||
* Save the first and last address of the pool of memory
|
||||
*/
|
||||
p_StartPoolAdd = p_pool;
|
||||
p_EndPoolAdd = p_pool + pool_size - 1;
|
||||
|
||||
UTIL_MM_Init(p_pool, pool_size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide a buffer
|
||||
* @note The buffer allocated to the user shall be at least sizeof(tListNode) bytes
|
||||
* to store the memory manager chaining information
|
||||
* During execution, this API shall not be interrupted with a call to either
|
||||
* MM_GetBuffer() or MM_ReleaseBuffer()
|
||||
* MM_GetBuffer() is called only from background so this will never happen
|
||||
* MM_ReleaseBuffer() is called from IPCC interrupt. Masking IPCC interrupt is
|
||||
* enough to comply to the requirement
|
||||
* Note that the primask bit cannot be used as the length of the critical section is too long compare to
|
||||
* the maximum latency of the BLE Irq. Therefore, the BLE Irq shall not be masked.
|
||||
*
|
||||
* @param size: The size of the buffer requested
|
||||
* @param cb: The callback to be called when a buffer is made available later on
|
||||
* if there is no buffer currently available when this API is called
|
||||
* @retval The buffer address when available or NULL when there is no buffer
|
||||
*/
|
||||
MM_pBufAdd_t MM_GetBuffer( uint32_t size, MM_pCb_t cb )
|
||||
{
|
||||
MM_pBufAdd_t buffer_address;
|
||||
/* uint32_t nvic_ipcc_status; */
|
||||
uint8_t allocation_exit = FALSE;
|
||||
|
||||
while( allocation_exit == FALSE )
|
||||
{
|
||||
|
||||
/* nvic_ipcc_status = NVIC_GetEnableIRQ(IPCC_C2_RX_C2_TX_HSEM_IRQn); */ /**< backup IPCC just in case it has been disabled by the user */
|
||||
/* NVIC_DisableIRQ(IPCC_C2_RX_C2_TX_HSEM_IRQn); */
|
||||
__disable_irq();
|
||||
buffer_address = (MM_pBufAdd_t)UTIL_MM_GetBuffer( size );
|
||||
__enable_irq();
|
||||
/*
|
||||
if(nvic_ipcc_status != 0)
|
||||
{
|
||||
NVIC_EnableIRQ(IPCC_C2_RX_C2_TX_HSEM_IRQn);
|
||||
}
|
||||
*/
|
||||
|
||||
if(buffer_address != 0)
|
||||
{
|
||||
if((buffer_address >= p_StartPoolAdd) && (buffer_address <= (p_EndPoolAdd - size + 1)))
|
||||
{
|
||||
/* The buffer is in a valid range */
|
||||
BufferFreeCb = 0;
|
||||
allocation_exit = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* The buffer is not in a valid range.
|
||||
* Keep the reference out of the memory pool and try again
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferFreeCb = cb;
|
||||
allocation_exit = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a buffer
|
||||
* During execution, this API shall not be interrupted with a call to either
|
||||
* MM_GetBuffer() or MM_ReleaseBuffer()
|
||||
* MM_GetBuffer() is called only from background so this will never happen
|
||||
* MM_ReleaseBuffer() is called from IPCC interrupt so it cannot be nested.
|
||||
* There is no need of a critical section
|
||||
* Note that anyway, the primask bit cannot be used as the length of the critical section
|
||||
* is too long compare to the maximum latency of the BLE Irq. Therefore, the BLE Irq shall not be masked.
|
||||
*
|
||||
* @param p_buffer: The data buffer address
|
||||
* @retval None
|
||||
*/
|
||||
void MM_ReleaseBuffer( MM_pBufAdd_t p_buffer )
|
||||
{
|
||||
if((p_buffer >= p_StartPoolAdd) && (p_buffer <= p_EndPoolAdd))
|
||||
{
|
||||
UTIL_MM_ReleaseBuffer( p_buffer );
|
||||
|
||||
if( BufferFreeCb )
|
||||
{
|
||||
/**
|
||||
* The application is waiting for a free buffer
|
||||
*/
|
||||
BufferFreeCb();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memory_manager.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for memory_manager.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2023 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef MEMORY_MANAGER_H
|
||||
#define MEMORY_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported defines -----------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef void (*MM_pCb_t)( void );
|
||||
typedef uint8_t (*MM_pBufAdd_t);
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void MM_Init(uint8_t *p_pool, uint32_t pool_size, uint32_t elt_size);
|
||||
MM_pBufAdd_t MM_GetBuffer(uint32_t size, MM_pCb_t cb );
|
||||
void MM_ReleaseBuffer( MM_pBufAdd_t p_buffer );
|
||||
|
||||
/* Exported functions to be implemented by the user if required ------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MEMORY_MANAGER_H */
|
||||
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.1
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32_mm.c
|
||||
* @author MCD Application Team
|
||||
* @brief Memory Manager Utility
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* A sample implementation of pvPortMalloc() and vPortFree() that combines
|
||||
* (coalescences) adjacent memory blocks as they are freed, and in so doing
|
||||
* limits memory fragmentation.
|
||||
*
|
||||
* See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
|
||||
* memory management pages of https://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include "utilities_common.h"
|
||||
#include "stm32_mm.h"
|
||||
|
||||
#undef PRIVILEGED_DATA
|
||||
#define PRIVILEGED_DATA
|
||||
|
||||
#undef PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_FUNCTION
|
||||
|
||||
#undef portBYTE_ALIGNMENT
|
||||
#define portBYTE_ALIGNMENT (8)
|
||||
|
||||
#undef portBYTE_ALIGNMENT_MASK
|
||||
#if portBYTE_ALIGNMENT == 8
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
#endif
|
||||
#if portBYTE_ALIGNMENT == 4
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
|
||||
#endif
|
||||
|
||||
/* No test marker by default. */
|
||||
#undef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
|
||||
#undef configASSERT
|
||||
#define configASSERT( x )
|
||||
|
||||
/* No tracing by default. */
|
||||
#undef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
|
||||
#undef traceFREE
|
||||
#define traceFREE( pvAddress, uiSize )
|
||||
|
||||
#undef vTaskSuspendAll
|
||||
#define vTaskSuspendAll()
|
||||
|
||||
#undef xTaskResumeAll
|
||||
#define xTaskResumeAll() (0)
|
||||
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#else
|
||||
PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
#endif
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
* of their memory address. */
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */
|
||||
size_t xBlockSize; /*<< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Inserts a block of memory that is being freed into the correct position in
|
||||
* the list of free memory blocks. The block being freed will be merged with
|
||||
* the block in front it and/or the block behind it if the memory blocks are
|
||||
* adjacent to each other.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Called automatically to setup the required heap structures the first time
|
||||
* pvPortMalloc() is called.
|
||||
*/
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
static void prvHeapInit( void ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The size of the structure placed at the beginning of each allocated memory
|
||||
* block must by correctly byte aligned. */
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
PRIVILEGED_DATA static BlockLink_t xStart, * pxEnd = NULL;
|
||||
|
||||
/* Keeps track of the number of calls to allocate and free memory as well as the
|
||||
* number of free bytes remaining, but says nothing about fragmentation. */
|
||||
PRIVILEGED_DATA static size_t xFreeBytesRemaining = 0U;
|
||||
PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = 0;
|
||||
PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = 0;
|
||||
|
||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
||||
* member of an BlockLink_t structure is set then the block belongs to the
|
||||
* application. When the bit is free the block is still part of the free heap
|
||||
* space. */
|
||||
PRIVILEGED_DATA static size_t xBlockAllocatedBit = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS == 0)
|
||||
void * UTIL_MM_GetBuffer( size_t xWantedSize )
|
||||
#else
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
#endif
|
||||
{
|
||||
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is
|
||||
* set. The top bit of the block size member of the BlockLink_t structure
|
||||
* is used to determine who owns the block - the application or the
|
||||
* kernel, so it must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
* of bytes. */
|
||||
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
* was not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
* single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
* by the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
xNumberOfSuccessfulAllocations++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS == 0)
|
||||
void UTIL_MM_ReleaseBuffer( void * pv )
|
||||
#else
|
||||
void vPortFree( void * pv )
|
||||
#endif
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
xNumberOfSuccessfulFrees++;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */
|
||||
#else
|
||||
void UTIL_MM_Init(uint8_t *p_pool, uint32_t pool_size)
|
||||
#endif
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
|
||||
#else
|
||||
size_t xTotalHeapSize;
|
||||
xTotalHeapSize = pool_size;
|
||||
#endif
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) p_pool;
|
||||
|
||||
if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( portBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) p_pool;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
|
||||
void vPortGetHeapStats( HeapStats_t * pxHeapStats )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||
* is initialised automatically when the first allocation is made. */
|
||||
if( pxBlock != NULL )
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Increment the number of blocks and record the largest block seen
|
||||
* so far. */
|
||||
xBlocks++;
|
||||
|
||||
if( pxBlock->xBlockSize > xMaxSize )
|
||||
{
|
||||
xMaxSize = pxBlock->xBlockSize;
|
||||
}
|
||||
|
||||
if( pxBlock->xBlockSize < xMinSize )
|
||||
{
|
||||
xMinSize = pxBlock->xBlockSize;
|
||||
}
|
||||
|
||||
/* Move to the next block in the chain until the last block is
|
||||
* reached. */
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
} while( pxBlock != pxEnd );
|
||||
}
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32_mm.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for stm32_mm.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef STM32_MM_H
|
||||
#define STM32_MM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported defines -----------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/**
|
||||
* @brief Initialize the Pool
|
||||
* @param p_pool: The pool of memory to manage
|
||||
* @param pool_size: The size of the pool
|
||||
* @retval None
|
||||
*/
|
||||
void UTIL_MM_Init(uint8_t *p_pool, uint32_t pool_size);
|
||||
|
||||
/**
|
||||
* @brief Provide a buffer
|
||||
* @param xWantedSize: The size of the buffer requested
|
||||
* @retval The buffer address when available or NULL when there is no buffer
|
||||
*/
|
||||
|
||||
void * UTIL_MM_GetBuffer(size_t xWantedSize);
|
||||
|
||||
/**
|
||||
* @brief Release a buffer
|
||||
* @param pv: The data buffer address
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void UTIL_MM_ReleaseBuffer( void * pv );
|
||||
|
||||
/* Exported functions to be implemented by the user if required ------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STM32_MM_H */
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf_antenna_switch.c
|
||||
* @author MCD Application Team
|
||||
* @brief RF related module to handle dedictated GPIOs for antenna switch
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rf_antenna_switch.h"
|
||||
#include "ll_intf.h"
|
||||
#include "app_conf.h"
|
||||
|
||||
#if (SUPPORT_AOA_AOD == 1) || (SUPPORT_ANT_DIV == 1)
|
||||
|
||||
static void RF_CONTROL_AntennaSwitch_Enable(void);
|
||||
static void RF_CONTROL_AntennaSwitch_Disable(void);
|
||||
|
||||
static void RF_CONTROL_AntennaSwitch_Enable(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
uint32_t table_size = sizeof(rt_antenna_switch_gpio_table)/sizeof(rt_antenna_switch_gpio_table[0]);
|
||||
|
||||
for(unsigned int cpt = 0; cpt<table_size; cpt++)
|
||||
{
|
||||
GPIO_InitStruct.Pin = rt_antenna_switch_gpio_table[cpt].GPIO_pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = rt_antenna_switch_gpio_table[cpt].GPIO_alternate;
|
||||
HAL_GPIO_Init(rt_antenna_switch_gpio_table[cpt].GPIO_port, &GPIO_InitStruct);
|
||||
}
|
||||
}
|
||||
|
||||
static void RF_CONTROL_AntennaSwitch_Disable(void)
|
||||
{
|
||||
uint32_t table_size = sizeof(rt_antenna_switch_gpio_table)/sizeof(rt_antenna_switch_gpio_table[0]);
|
||||
|
||||
for(unsigned int cpt = 0; cpt<table_size; cpt++)
|
||||
{
|
||||
HAL_GPIO_DeInit(rt_antenna_switch_gpio_table[cpt].GPIO_port, rt_antenna_switch_gpio_table[cpt].GPIO_pin);
|
||||
}
|
||||
}
|
||||
|
||||
void RF_CONTROL_AntennaSwitch(rf_antenna_switch_state_t state)
|
||||
{
|
||||
#if (SUPPORT_AOA_AOD == 1)
|
||||
ble_stat_t status = GENERAL_FAILURE;
|
||||
#endif
|
||||
|
||||
if(state == RF_ANTSW_ENABLE)
|
||||
{
|
||||
#if (SUPPORT_AOA_AOD == 1)
|
||||
status = ll_intf_set_num_of_antennas(CFG_RADIO_NUM_OF_ANTENNAS);
|
||||
if(status != SUCCESS)
|
||||
{
|
||||
/* Specified number of antennas is not supported */
|
||||
assert_param(0);
|
||||
return;
|
||||
}
|
||||
#endif /* SUPPORT_AOA_AOD */
|
||||
RF_CONTROL_AntennaSwitch_Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
RF_CONTROL_AntennaSwitch_Disable();
|
||||
}
|
||||
}
|
||||
|
||||
#else /* SUPPORT_AOA_AOD || SUPPORT_ANT_DIV */
|
||||
void RF_CONTROL_AntennaSwitch(rf_antenna_switch_state_t state)
|
||||
{
|
||||
/* AoA-AoD or antenna diversity feature is not supported with this Link Layer configuration */
|
||||
assert_param(0);
|
||||
}
|
||||
#endif /* SUPPORT_AOA_AOD || SUPPORT_ANT_DIV */
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf_antenna_switch.h
|
||||
* @author MCD Application Team
|
||||
* @brief RF related module to handle dedictated GPIOs for antenna switch
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RF_ANTENNA_SWITCH_H
|
||||
#define RF_ANTENNA_SWITCH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stm32wbaxx.h"
|
||||
|
||||
#define RF_ANTSW0 {GPIOA, GPIO_PIN_12, GPIO_AF11_RF_ANTSW0}
|
||||
#define RF_ANTSW1 {GPIOA, GPIO_PIN_11, GPIO_AF11_RF_ANTSW1}
|
||||
#define RF_ANTSW2 {GPIOB, GPIO_PIN_2, GPIO_AF11_RF_ANTSW2}
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef* GPIO_port;
|
||||
uint16_t GPIO_pin;
|
||||
uint8_t GPIO_alternate;
|
||||
} st_gpio_antsw_t;
|
||||
|
||||
typedef enum {
|
||||
RF_ANTSW_DISABLE = 0,
|
||||
RF_ANTSW_ENABLE
|
||||
} rf_antenna_switch_state_t;
|
||||
|
||||
static const st_gpio_antsw_t rt_antenna_switch_gpio_table[] =
|
||||
{
|
||||
RF_ANTSW0,
|
||||
RF_ANTSW1,
|
||||
RF_ANTSW2
|
||||
};
|
||||
|
||||
void RF_CONTROL_AntennaSwitch(rf_antenna_switch_state_t state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RF_ANTENNA_SWITCH_H */
|
||||
@@ -0,0 +1,89 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf_external_pa.c
|
||||
* @author MCD Application Team
|
||||
* @brief RF related module to handle dedictated GPIOs for external PA
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 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 */
|
||||
|
||||
#include "rf_external_pa.h"
|
||||
#include "power_table.h"
|
||||
#include "ll_intf.h"
|
||||
#include "app_conf.h"
|
||||
|
||||
static void RF_CONTROL_ExternalPA_Enable(void);
|
||||
static void RF_CONTROL_ExternalPA_Disable(void);
|
||||
static uint8_t RF_CONTROL_ExternalPA_Enable_cb(uint8_t epa_enable);
|
||||
|
||||
static void RF_CONTROL_ExternalPA_Enable(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
uint32_t table_size = sizeof(rf_external_pa_gpio_table)/sizeof(rf_external_pa_gpio_table[0]);
|
||||
|
||||
for(unsigned int cpt = 0; cpt<table_size; cpt++)
|
||||
{
|
||||
GPIO_InitStruct.Pin = rf_external_pa_gpio_table[cpt].GPIO_pin;
|
||||
GPIO_InitStruct.Mode = rf_external_pa_gpio_table[cpt].GPIO_mode;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = rf_external_pa_gpio_table[cpt].GPIO_alternate;
|
||||
HAL_GPIO_Init(rf_external_pa_gpio_table[cpt].GPIO_port, &GPIO_InitStruct);
|
||||
}
|
||||
}
|
||||
|
||||
static void RF_CONTROL_ExternalPA_Disable(void)
|
||||
{
|
||||
uint32_t table_size = sizeof(rf_external_pa_gpio_table)/sizeof(rf_external_pa_gpio_table[0]);
|
||||
|
||||
for(unsigned int cpt = 0; cpt<table_size; cpt++)
|
||||
{
|
||||
HAL_GPIO_DeInit(rf_external_pa_gpio_table[cpt].GPIO_port, rf_external_pa_gpio_table[cpt].GPIO_pin);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t RF_CONTROL_ExternalPA_Enable_cb(uint8_t epa_enable)
|
||||
{
|
||||
if(epa_enable == 1)
|
||||
{
|
||||
HAL_GPIO_WritePin(rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_port, rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_pin, GPIO_PIN_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_port, rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RF_CONTROL_ExternalPA(rf_external_pa_state_t state)
|
||||
{
|
||||
ble_stat_t status = GENERAL_FAILURE;
|
||||
|
||||
if(state == RF_EPA_ENABLE)
|
||||
{
|
||||
status = ll_tx_pwr_if_epa_init(1, RF_CONTROL_ExternalPA_Enable_cb);
|
||||
if(status != SUCCESS)
|
||||
{
|
||||
/* EPA callback is not defined */
|
||||
assert_param(0);
|
||||
return;
|
||||
}
|
||||
RF_CONTROL_ExternalPA_Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
RF_CONTROL_ExternalPA_Disable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rf_external_pa.h
|
||||
* @author MCD Application Team
|
||||
* @brief RF related module to handle dedictated GPIOs for external PA
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 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 */
|
||||
#ifndef RF_EXTERNAL_PA_H
|
||||
#define RF_EXTERNAL_PA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stm32wbaxx.h"
|
||||
|
||||
#define RF_EPA_CSD {GPIOA, GPIO_PIN_9, GPIO_MODE_OUTPUT_PP, GPIO_AF15_EVENTOUT}
|
||||
#define RF_EPA_CTX {GPIOB, GPIO_PIN_15, GPIO_MODE_AF_PP, GPIO_AF11_RF_IO1}
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef* GPIO_port;
|
||||
uint16_t GPIO_pin;
|
||||
uint32_t GPIO_mode;
|
||||
uint8_t GPIO_alternate;
|
||||
} st_gpio_epa_t;
|
||||
|
||||
typedef enum {
|
||||
RF_EPA_DISABLE = 0,
|
||||
RF_EPA_ENABLE
|
||||
} rf_external_pa_state_t;
|
||||
|
||||
typedef enum {
|
||||
RF_EPA_SIGNAL_CSD = 0,
|
||||
RF_EPA_SIGNAL_CTX
|
||||
} rf_external_pa_signal_t;
|
||||
|
||||
static const st_gpio_epa_t rf_external_pa_gpio_table[] =
|
||||
{
|
||||
[RF_EPA_SIGNAL_CSD] = RF_EPA_CSD,
|
||||
[RF_EPA_SIGNAL_CTX] = RF_EPA_CTX
|
||||
};
|
||||
|
||||
void RF_CONTROL_ExternalPA(rf_external_pa_state_t state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RF_EXTERNAL_PA_H */
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file RTDebug.c
|
||||
* @author MCD Application Team
|
||||
* @brief Real Time Debug module API definition
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "RTDebug.h"
|
||||
#include "local_debug_tables.h"
|
||||
#include "stm32wbaxx_hal.h"
|
||||
#include <assert.h>
|
||||
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
static_assert((sizeof(general_debug_table)/sizeof(st_gpio_debug_t)) == RT_DEBUG_SIGNALS_TOTAL_NUM,
|
||||
"Debug signals number is different from debug signal table size."
|
||||
);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
|
||||
/***********************/
|
||||
/** System debug APIs **/
|
||||
/***********************/
|
||||
|
||||
void SYSTEM_DEBUG_SIGNAL_SET(system_debug_signal_t signal)
|
||||
{
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
GENERIC_DEBUG_GPIO_SET(signal, system_debug_table);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
}
|
||||
|
||||
void SYSTEM_DEBUG_SIGNAL_RESET(system_debug_signal_t signal)
|
||||
{
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
GENERIC_DEBUG_GPIO_RESET(signal, system_debug_table);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
}
|
||||
|
||||
void SYSTEM_DEBUG_SIGNAL_TOGGLE(system_debug_signal_t signal)
|
||||
{
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
GENERIC_DEBUG_GPIO_TOGGLE(signal, system_debug_table);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/** Link Layer debug APIs **/
|
||||
/***************************/
|
||||
|
||||
/* Link Layer debug API definition */
|
||||
void LINKLAYER_DEBUG_SIGNAL_SET(linklayer_debug_signal_t signal)
|
||||
{
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
GENERIC_DEBUG_GPIO_SET(signal, linklayer_debug_table);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
}
|
||||
|
||||
void LINKLAYER_DEBUG_SIGNAL_RESET(linklayer_debug_signal_t signal)
|
||||
{
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
GENERIC_DEBUG_GPIO_RESET(signal, linklayer_debug_table);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
}
|
||||
|
||||
void LINKLAYER_DEBUG_SIGNAL_TOGGLE(linklayer_debug_signal_t signal)
|
||||
{
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
GENERIC_DEBUG_GPIO_TOGGLE(signal, linklayer_debug_table);
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file RTDebug.h
|
||||
* @author MCD Application Team
|
||||
* @brief Real Time Debug module API declaration
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_DEBUG_H
|
||||
#define SYSTEM_DEBUG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "debug_config.h"
|
||||
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
|
||||
/**************************************************************/
|
||||
/** Generic macros for local signal table index recuperation **/
|
||||
/** and global signal table GPIO manipulation **/
|
||||
/**************************************************************/
|
||||
|
||||
#define GENERIC_DEBUG_GPIO_SET(signal, table) do { \
|
||||
uint32_t debug_table_idx = 0; \
|
||||
if(signal >= sizeof(table)) \
|
||||
{ \
|
||||
return; \
|
||||
} \
|
||||
debug_table_idx = table[signal]; \
|
||||
if(debug_table_idx != RT_DEBUG_SIGNAL_UNUSED) \
|
||||
{ \
|
||||
LL_GPIO_SetOutputPin(general_debug_table[debug_table_idx].GPIO_port, \
|
||||
general_debug_table[debug_table_idx].GPIO_pin); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define GENERIC_DEBUG_GPIO_RESET(signal, table) do { \
|
||||
uint32_t debug_table_idx = 0; \
|
||||
if(signal >= sizeof(table)) \
|
||||
{ \
|
||||
return; \
|
||||
} \
|
||||
debug_table_idx = table[signal]; \
|
||||
if(debug_table_idx != RT_DEBUG_SIGNAL_UNUSED) \
|
||||
{ \
|
||||
LL_GPIO_ResetOutputPin(general_debug_table[debug_table_idx].GPIO_port, \
|
||||
general_debug_table[debug_table_idx].GPIO_pin); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define GENERIC_DEBUG_GPIO_TOGGLE(signal, table) do { \
|
||||
uint32_t debug_table_idx = 0; \
|
||||
if(signal >= sizeof(table)) \
|
||||
{ \
|
||||
return; \
|
||||
} \
|
||||
debug_table_idx = table[signal]; \
|
||||
if(debug_table_idx != RT_DEBUG_SIGNAL_UNUSED) \
|
||||
{ \
|
||||
LL_GPIO_TogglePin(general_debug_table[debug_table_idx].GPIO_port, \
|
||||
general_debug_table[debug_table_idx].GPIO_pin); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
|
||||
/* System debug API definition */
|
||||
void SYSTEM_DEBUG_SIGNAL_SET(system_debug_signal_t signal);
|
||||
void SYSTEM_DEBUG_SIGNAL_RESET(system_debug_signal_t signal);
|
||||
void SYSTEM_DEBUG_SIGNAL_TOGGLE(system_debug_signal_t signal);
|
||||
|
||||
/* Link Layer debug API definition */
|
||||
void LINKLAYER_DEBUG_SIGNAL_SET(linklayer_debug_signal_t signal);
|
||||
void LINKLAYER_DEBUG_SIGNAL_RESET(linklayer_debug_signal_t signal);
|
||||
void LINKLAYER_DEBUG_SIGNAL_TOGGLE(linklayer_debug_signal_t signal);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SYSTEM_DEBUG_H */
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file RTDebug_dtb.c
|
||||
* @author MCD Application Team
|
||||
* @brief Real Time Debug module API definition for DTB usage
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DEBUG DTB interface is INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT.
|
||||
* It provides HW signals from RF PHY activity.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "RTDebug_dtb.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
#if(CFG_RT_DEBUG_DTB == 1)
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void RT_DEBUG_SetDTBMode(uint8_t dtb, uint8_t mode);
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
static void RT_DEBUG_SetDTBMode(uint8_t dtb, uint8_t mode)
|
||||
{
|
||||
/* Set SYSCFG for DTB */
|
||||
uint32_t addr = (uint32_t)(&SYSCFG->SECCFGR);
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
addr += 0x100; /* contains SYSCFG->DBTCR address */
|
||||
|
||||
/* Keep others DTB in current modes */
|
||||
*(uint32_t*)addr |= (0xF<<(dtb*4)); /* Selected DTB unmask mode */
|
||||
*(uint32_t*)addr ^= (0xF<<(dtb*4)); /* Selected DTB unset mode */
|
||||
|
||||
/* Selected DTB set to mode */
|
||||
*(uint32_t*)addr |= (mode<<(dtb*4));
|
||||
}
|
||||
|
||||
void RT_DEBUG_DTBInit(void)
|
||||
{
|
||||
/** access_match PA7 DTB[7] on TL_10 **/
|
||||
/*
|
||||
LL_GPIO_SetPinSpeed(GPIOA,LL_GPIO_PIN_7,LL_GPIO_SPEED_FREQ_HIGH);
|
||||
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_7,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_7,LL_GPIO_AF_15);
|
||||
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_7);
|
||||
*/
|
||||
|
||||
/** long_range_iq_vld PA6 DTB[6] on TL_9 **/
|
||||
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_6,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_6,LL_GPIO_AF_15);
|
||||
|
||||
|
||||
/** tx_data PA5 DTB[5] on TL_8 **/
|
||||
/*
|
||||
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_5,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_5,LL_GPIO_AF_15);
|
||||
*/
|
||||
|
||||
/** rx_data PB9 DTB[4] on TL_31 **/
|
||||
/*
|
||||
LL_GPIO_SetPinMode(GPIOB,LL_GPIO_PIN_9,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_8_15(GPIOB,LL_GPIO_PIN_9,LL_GPIO_AF_15);
|
||||
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTB, LL_PWR_GPIO_PIN_9);
|
||||
*/
|
||||
|
||||
/** tx_data_clk PB8 DTB[3] on TL_30 **/
|
||||
/*
|
||||
LL_GPIO_SetPinMode(GPIOB,LL_GPIO_PIN_8,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_8_15(GPIOB,LL_GPIO_PIN_8,LL_GPIO_AF_15);
|
||||
*/
|
||||
|
||||
/** rx_data_clk PA2 DTB[2] on TL_3 **/
|
||||
/*
|
||||
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_2,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_2,LL_GPIO_AF_15);
|
||||
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_2);
|
||||
*/
|
||||
|
||||
/** tx_on PA1 DTB[1] on TL_2 **/
|
||||
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_1,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_1,LL_GPIO_AF_15);
|
||||
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_1);
|
||||
|
||||
/** rx_on PA0 DTB[0] on TL_1 **/
|
||||
/*
|
||||
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_0,LL_GPIO_MODE_ALTERNATE);
|
||||
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_0,LL_GPIO_AF_15);
|
||||
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_0);
|
||||
*/
|
||||
|
||||
/* Set SYSCFG for DTB */
|
||||
uint32_t addr = (uint32_t)(&SYSCFG->SECCFGR);
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
addr += 0x100; /* contains SYSCFG->DBTCR address */
|
||||
|
||||
/* Default DTB in test mode 0 */
|
||||
*(uint32_t*)addr = 0x00000000;
|
||||
}
|
||||
|
||||
/* Public functions ----------------------------------------------------------*/
|
||||
void RT_DEBUG_DTBConfig(void)
|
||||
{
|
||||
|
||||
/*
|
||||
** Monitor DTB **
|
||||
* A0 o PA0 AF15 DTB[0] mode 1 rx_on
|
||||
* A1 o PA1 AF15 DTB[1] mode 1 tx_on
|
||||
* A2 o PB9 AF15 DTB[4] mode 5 radio_bbclk
|
||||
* A3 o PA7 AF15 DTB[7] mode 3 slptmr_irq
|
||||
* A4 o PA2 AF15 DTB[2] mode 5 CM33_sleepdeep
|
||||
* A5 o PA6 AF00 PWR_CSTOP
|
||||
* A6 o PA8 as SYSclk source
|
||||
* A7 o PB1 Monitor wakeup GPIO
|
||||
* A8 o PB0 Debug PIN
|
||||
* A9 o PC0 o_pm_sleep_sw
|
||||
* A10 o PC1 o_pm_act_com_sw
|
||||
**/
|
||||
|
||||
RT_DEBUG_SetDTBMode(6, 3) ; /* Radio IRQ */
|
||||
RT_DEBUG_SetDTBMode(1, 1); /* tx_on */
|
||||
|
||||
//RT_DEBUG_SetDTBMode(0, 1); /* rx_on */
|
||||
//RT_DEBUG_SetDTBMode(1, 3); /* sleep timer irq */
|
||||
//RT_DEBUG_SetDTBMode(2, 5); /* CM33_sleepdeep */
|
||||
//RT_DEBUG_SetDTBMode(4, 5); /* radio_bbclk */
|
||||
//RT_DEBUG_SetDTBMode(7, 3); /* slptm_irq */
|
||||
//RT_DEBUG_SetDTBMode(7, 5); /* radio_bus_clk */
|
||||
//RT_DEBUG_SetDTBMode(7, 6); /* test tm 00 */
|
||||
//RT_DEBUG_SetDTBMode(6, 6); /* test tm 01 */
|
||||
}
|
||||
|
||||
#endif /* CFG_RT_DEBUG_DTB */
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file RTDebug_dtb.h
|
||||
* @author MCD Application Team
|
||||
* @brief Real Time Debug module API declaration for DTB usage
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RT_DEBUG_DTB_H
|
||||
#define RT_DEBUG_DTB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The DEBUG DTB interface is INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT.
|
||||
* It provides HW signals from RF PHY activity.
|
||||
*/
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
#if(CFG_RT_DEBUG_DTB == 1)
|
||||
void RT_DEBUG_DTBConfig(void);
|
||||
void RT_DEBUG_DTBInit(void);
|
||||
#endif /* CFG_RT_DEBUG_DTB */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RT_DEBUG_DTB_H */
|
||||
|
||||
@@ -0,0 +1,833 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file debug_signals.h
|
||||
* @author MCD Application Team
|
||||
* @brief Real Time Debug module System and Link Layer signal definition
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_SIGNALS_H
|
||||
#define DEBUG_SIGNALS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "bsp.h"
|
||||
|
||||
/**************************************************/
|
||||
/** Specific Link Layer debug signals definition **/
|
||||
/**************************************************/
|
||||
typedef Debug_GPIO_t linklayer_debug_signal_t;
|
||||
|
||||
/**********************************************/
|
||||
/** Specific System debug signals definition **/
|
||||
/**********************************************/
|
||||
typedef enum {
|
||||
ADC_ACTIVATION,
|
||||
ADC_DEACTIVATION,
|
||||
ADC_TEMPERATURE_ACQUISITION,
|
||||
RNG_ENABLE,
|
||||
RNG_DISABLE,
|
||||
RNG_GEN_RAND_NUM,
|
||||
LOW_POWER_STOP_MODE_ENTER,
|
||||
LOW_POWER_STOP_MODE_EXIT,
|
||||
LOW_POWER_STOP_MODE_ACTIVE,
|
||||
LOW_POWER_STOP2_MODE_ENTER,
|
||||
LOW_POWER_STOP2_MODE_EXIT,
|
||||
LOW_POWER_STOP2_MODE_ACTIVE,
|
||||
LOW_POWER_STANDBY_MODE_ENTER,
|
||||
LOW_POWER_STANDBY_MODE_EXIT,
|
||||
LOW_POWER_STANDBY_MODE_ACTIVE,
|
||||
SCM_SETUP,
|
||||
SCM_SYSTEM_CLOCK_CONFIG,
|
||||
SCM_HSERDY_ISR,
|
||||
} system_debug_signal_t;
|
||||
|
||||
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
|
||||
|
||||
/*************************************/
|
||||
/** Global debug signals definition **/
|
||||
/*************************************/
|
||||
|
||||
typedef enum {
|
||||
RT_DEBUG_SIGNAL_UNUSED = 0x0,
|
||||
|
||||
/********************/
|
||||
/** System signals **/
|
||||
/********************/
|
||||
|
||||
#if (USE_RT_DEBUG_SCM_SETUP == 1)
|
||||
RT_DEBUG_SCM_SETUP,
|
||||
#endif /* USE_RT_DEBUG_SCM_SETUP */
|
||||
|
||||
#if (USE_RT_DEBUG_SCM_HSERDY_ISR == 1)
|
||||
RT_DEBUG_SCM_HSERDY_ISR,
|
||||
#endif /* USE_RT_DEBUG_SCM_HSERDY_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_SCM_SYSTEM_CLOCK_CONFIG == 1)
|
||||
RT_DEBUG_SCM_SYSTEM_CLOCK_CONFIG,
|
||||
#endif /* USE_RT_DEBUG_SCM_SYSTEM_CLOCK_CONFIG */
|
||||
|
||||
#if (USE_RT_DEBUG_ADC_ACTIVATION == 1)
|
||||
RT_DEBUG_ADC_ACTIVATION,
|
||||
#endif /* USE_RT_DEBUG_ADC_ACTIVATION */
|
||||
|
||||
#if (USE_RT_DEBUG_ADC_DEACTIVATION == 1)
|
||||
RT_DEBUG_ADC_DEACTIVATION,
|
||||
#endif /* USE_RT_DEBUG_ADC_DEACTIVATION */
|
||||
|
||||
#if (USE_RT_DEBUG_ADC_TEMPERATURE_ACQUISITION == 1)
|
||||
RT_DEBUG_ADC_TEMPERATURE_ACQUISITION,
|
||||
#endif /* USE_RT_DEBUG_ADC_TEMPERATURE_ACQUISITION */
|
||||
|
||||
#if (USE_RT_DEBUG_RNG_ENABLE == 1)
|
||||
RT_DEBUG_RNG_ENABLE,
|
||||
#endif /* USE_RT_DEBUG_RNG_ENABLE */
|
||||
|
||||
#if (USE_RT_DEBUG_RNG_DISABLE == 1)
|
||||
RT_DEBUG_RNG_DISABLE,
|
||||
#endif /* USE_RT_DEBUG_RNG_DISABLE */
|
||||
|
||||
#if (USE_RT_DEBUG_RNG_GEN_RAND_NUM == 1)
|
||||
RT_DEBUG_RNG_GEN_RAND_NUM,
|
||||
#endif /* USE_RT_DEBUG_RNG_GEN_RAND_NUM */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STOP_MODE_ENTER == 1)
|
||||
RT_DEBUG_LOW_POWER_STOP_MODE_ENTER,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STOP_MODE_ENTER */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STOP_MODE_EXIT == 1)
|
||||
RT_DEBUG_LOW_POWER_STOP_MODE_EXIT,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STOP_MODE_EXIT */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STOP_MODE_ACTIVE == 1)
|
||||
RT_DEBUG_LOW_POWER_STOP_MODE_ACTIVE,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STOP_MODE_ACTIVE */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ENTER == 1)
|
||||
RT_DEBUG_LOW_POWER_STOP2_MODE_ENTER,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ENTER */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STOP2_MODE_EXIT == 1)
|
||||
RT_DEBUG_LOW_POWER_STOP2_MODE_EXIT,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STOP2_MODE_EXIT */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ACTIVE == 1)
|
||||
RT_DEBUG_LOW_POWER_STOP2_MODE_ACTIVE,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ACTIVE */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ENTER == 1)
|
||||
RT_DEBUG_LOW_POWER_STANDBY_MODE_ENTER,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ENTER */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_EXIT == 1)
|
||||
RT_DEBUG_LOW_POWER_STANDBY_MODE_EXIT,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_EXIT */
|
||||
|
||||
#if (USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ACTIVE == 1)
|
||||
RT_DEBUG_LOW_POWER_STANDBY_MODE_ACTIVE,
|
||||
#endif /* USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ACTIVE */
|
||||
|
||||
/************************/
|
||||
/** Link Layer signals **/
|
||||
/************************/
|
||||
|
||||
#if (USE_RT_DEBUG_HCI_READ_DONE == 1)
|
||||
RT_DEBUG_HCI_READ_DONE,
|
||||
#endif /* USE_RT_DEBUG_HCI_READ_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_HCI_RCVD_CMD == 1)
|
||||
RT_DEBUG_HCI_RCVD_CMD,
|
||||
#endif /* USE_RT_DEBUG_HCI_RCVD_CMD */
|
||||
|
||||
#if (USE_RT_DEBUG_HCI_WRITE_DONE == 1)
|
||||
RT_DEBUG_HCI_WRITE_DONE,
|
||||
#endif /* USE_RT_DEBUG_HCI_WRITE_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EVNT_UPDATE == 1)
|
||||
RT_DEBUG_SCHDLR_EVNT_UPDATE,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EVNT_UPDATE */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_TIMER_SET == 1)
|
||||
RT_DEBUG_SCHDLR_TIMER_SET,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_TIMER_SET */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_PHY_CLBR_TIMER == 1)
|
||||
RT_DEBUG_SCHDLR_PHY_CLBR_TIMER,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_PHY_CLBR_TIMER */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EVNT_SKIPPED == 1)
|
||||
RT_DEBUG_SCHDLR_EVNT_SKIPPED,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EVNT_SKIPPED */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_HNDL_NXT_TRACE == 1)
|
||||
RT_DEBUG_SCHDLR_HNDL_NXT_TRACE,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_HNDL_NXT_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_DETEDTED == 1)
|
||||
RT_DEBUG_ACTIVE_SCHDLR_NEAR_DETEDTED,
|
||||
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_DETEDTED */
|
||||
|
||||
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_GAP_CHECK == 1)
|
||||
RT_DEBUG_ACTIVE_SCHDLR_NEAR_GAP_CHECK,
|
||||
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_GAP_CHECK */
|
||||
|
||||
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TIME_CHECK == 1)
|
||||
RT_DEBUG_ACTIVE_SCHDLR_NEAR_TIME_CHECK,
|
||||
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TIME_CHECK */
|
||||
|
||||
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TRACE == 1)
|
||||
RT_DEBUG_ACTIVE_SCHDLR_NEAR_TRACE,
|
||||
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EVNT_RGSTR == 1)
|
||||
RT_DEBUG_SCHDLR_EVNT_RGSTR,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EVNT_RGSTR */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_ADD_CONFLICT_Q == 1)
|
||||
RT_DEBUG_SCHDLR_ADD_CONFLICT_Q,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_ADD_CONFLICT_Q */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_HNDL_MISSED_EVNT == 1)
|
||||
RT_DEBUG_SCHDLR_HNDL_MISSED_EVNT,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_HNDL_MISSED_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_UNRGSTR_EVNT == 1)
|
||||
RT_DEBUG_SCHDLR_UNRGSTR_EVNT,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_UNRGSTR_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_TRACE == 1)
|
||||
RT_DEBUG_SCHDLR_EXEC_EVNT_TRACE,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_PROFILE == 1)
|
||||
RT_DEBUG_SCHDLR_EXEC_EVNT_PROFILE,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_PROFILE */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_ERROR == 1)
|
||||
RT_DEBUG_SCHDLR_EXEC_EVNT_ERROR,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_ERROR */
|
||||
|
||||
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_WINDOW_WIDENING == 1)
|
||||
RT_DEBUG_SCHDLR_EXEC_EVNT_WINDOW_WIDENING,
|
||||
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_WINDOW_WIDENING */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_CMN_CLR_ISR == 1)
|
||||
RT_DEBUG_LLHWC_CMN_CLR_ISR,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_CMN_CLR_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLWCC_CMN_HG_ISR == 1)
|
||||
RT_DEBUG_LLWCC_CMN_HG_ISR,
|
||||
#endif /* USE_RT_DEBUG_LLWCC_CMN_HG_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_CMN_LW_ISR == 1)
|
||||
RT_DEBUG_LLHWC_CMN_LW_ISR,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_CMN_LW_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_CMN_CLR_TIMER_ERROR == 1)
|
||||
RT_DEBUG_LLHWC_CMN_CLR_TIMER_ERROR,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_CMN_CLR_TIMER_ERROR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_LL_ISR == 1)
|
||||
RT_DEBUG_LLHWC_LL_ISR,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_LL_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_SPLTMR_SET == 1)
|
||||
RT_DEBUG_LLHWC_SPLTMR_SET,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_SPLTMR_SET */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_SPLTMR_GET == 1)
|
||||
RT_DEBUG_LLHWC_SPLTMR_GET,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_SPLTMR_GET */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_LOW_ISR == 1)
|
||||
RT_DEBUG_LLHWC_LOW_ISR,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_LOW_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_STOP_SCN == 1)
|
||||
RT_DEBUG_LLHWC_STOP_SCN,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_STOP_SCN */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_WAIT_ENVT_ON_AIR == 1)
|
||||
RT_DEBUG_LLHWC_WAIT_ENVT_ON_AIR,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_WAIT_ENVT_ON_AIR */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_SET_CONN_EVNT_PARAM == 1)
|
||||
RT_DEBUG_LLHWC_SET_CONN_EVNT_PARAM,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_SET_CONN_EVNT_PARAM */
|
||||
|
||||
#if (USE_RT_DEBUG_POST_EVNT == 1)
|
||||
RT_DEBUG_POST_EVNT,
|
||||
#endif /* USE_RT_DEBUG_POST_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_HNDL_ALL_EVNTS == 1)
|
||||
RT_DEBUG_HNDL_ALL_EVNTS,
|
||||
#endif /* USE_RT_DEBUG_HNDL_ALL_EVNTS */
|
||||
|
||||
#if (USE_RT_DEBUG_PROCESS_EVNT == 1)
|
||||
RT_DEBUG_PROCESS_EVNT,
|
||||
#endif /* USE_RT_DEBUG_PROCESS_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_PROCESS_ISO_DATA == 1)
|
||||
RT_DEBUG_PROCESS_ISO_DATA,
|
||||
#endif /* USE_RT_DEBUG_PROCESS_ISO_DATA */
|
||||
|
||||
#if (USE_RT_DEBUG_ALLOC_TX_ISO_EMPTY_PKT == 1)
|
||||
RT_DEBUG_ALLOC_TX_ISO_EMPTY_PKT,
|
||||
#endif /* USE_RT_DEBUG_ALLOC_TX_ISO_EMPTY_PKT */
|
||||
|
||||
#if (USE_RT_DEBUG_BIG_FREE_EMPTY_PKTS == 1)
|
||||
RT_DEBUG_BIG_FREE_EMPTY_PKTS,
|
||||
#endif /* USE_RT_DEBUG_BIG_FREE_EMPTY_PKTS */
|
||||
|
||||
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_OK == 1)
|
||||
RT_DEBUG_RECOMBINE_UNFRMD_DATA_OK,
|
||||
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_OK */
|
||||
|
||||
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_CRC == 1)
|
||||
RT_DEBUG_RECOMBINE_UNFRMD_DATA_CRC,
|
||||
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_CRC */
|
||||
|
||||
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_NoRX == 1)
|
||||
RT_DEBUG_RECOMBINE_UNFRMD_DATA_NoRX,
|
||||
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_NoRX */
|
||||
|
||||
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_TRACE == 1)
|
||||
RT_DEBUG_RECOMBINE_UNFRMD_DATA_TRACE,
|
||||
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_ISO_HNDL_SDU == 1)
|
||||
RT_DEBUG_ISO_HNDL_SDU,
|
||||
#endif /* USE_RT_DEBUG_ISO_HNDL_SDU */
|
||||
|
||||
#if (USE_RT_DEBUG_LL_INTF_INIT == 1)
|
||||
RT_DEBUG_LL_INTF_INIT,
|
||||
#endif /* USE_RT_DEBUG_LL_INTF_INIT */
|
||||
|
||||
#if (USE_RT_DEBUG_DATA_TO_CNTRLR == 1)
|
||||
RT_DEBUG_DATA_TO_CNTRLR,
|
||||
#endif /* USE_RT_DEBUG_DATA_TO_CNTRLR */
|
||||
|
||||
#if (USE_RT_DEBUG_FREE_LL_PKT_HNDLR == 1)
|
||||
RT_DEBUG_FREE_LL_PKT_HNDLR,
|
||||
#endif /* USE_RT_DEBUG_FREE_LL_PKT_HNDLR */
|
||||
|
||||
#if (USE_RT_DEBUG_PHY_INIT_CLBR_TRACE == 1)
|
||||
RT_DEBUG_PHY_INIT_CLBR_TRACE,
|
||||
#endif /* USE_RT_DEBUG_PHY_INIT_CLBR_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_PHY_RUNTIME_CLBR_TRACE == 1)
|
||||
RT_DEBUG_PHY_RUNTIME_CLBR_TRACE,
|
||||
#endif /* USE_RT_DEBUG_PHY_RUNTIME_CLBR_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_PHY_CLBR_ISR == 1)
|
||||
RT_DEBUG_PHY_CLBR_ISR,
|
||||
#endif /* USE_RT_DEBUG_PHY_CLBR_ISR */
|
||||
|
||||
#if (USE_RT_DEBUG_PHY_INIT_CLBR_SINGLE_CH == 1)
|
||||
RT_DEBUG_PHY_INIT_CLBR_SINGLE_CH,
|
||||
#endif /* USE_RT_DEBUG_PHY_INIT_CLBR_SINGLE_CH */
|
||||
|
||||
#if (USE_RT_DEBUG_PHY_CLBR_STRTD == 1)
|
||||
RT_DEBUG_PHY_CLBR_STRTD,
|
||||
#endif /* USE_RT_DEBUG_PHY_CLBR_STRTD */
|
||||
|
||||
#if (USE_RT_DEBUG_PHY_CLBR_EXEC == 1)
|
||||
RT_DEBUG_PHY_CLBR_EXEC,
|
||||
#endif /* USE_RT_DEBUG_PHY_CLBR_EXEC */
|
||||
|
||||
#if (USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_CLBR_ACTV == 1)
|
||||
RT_DEBUG_RCO_STRT_STOP_RUNTIME_CLBR_ACTV,
|
||||
#endif /* USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_CLBR_ACTV */
|
||||
|
||||
#if (USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_RCO_CLBR == 1)
|
||||
RT_DEBUG_RCO_STRT_STOP_RUNTIME_RCO_CLBR,
|
||||
#endif /* USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_RCO_CLBR */
|
||||
|
||||
#if (USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_SWT == 1)
|
||||
RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_SWT,
|
||||
#endif /* USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_SWT */
|
||||
|
||||
#if (USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_TRACE == 1)
|
||||
RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_TRACE,
|
||||
#endif /* USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_RCO_ISR_TRACE == 1)
|
||||
RT_DEBUG_RCO_ISR_TRACE,
|
||||
#endif /* USE_RT_DEBUG_RCO_ISR_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_RCO_ISR_COMPENDATE == 1)
|
||||
RT_DEBUG_RCO_ISR_COMPENDATE,
|
||||
#endif /* USE_RT_DEBUG_RCO_ISR_COMPENDATE */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_STRT_TX == 1)
|
||||
RT_DEBUG_RAL_STRT_TX,
|
||||
#endif /* USE_RT_DEBUG_RAL_STRT_TX */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_ISR_TIMER_ERROR == 1)
|
||||
RT_DEBUG_RAL_ISR_TIMER_ERROR,
|
||||
#endif /* USE_RT_DEBUG_RAL_ISR_TIMER_ERROR */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_ISR_TRACE == 1)
|
||||
RT_DEBUG_RAL_ISR_TRACE,
|
||||
#endif /* USE_RT_DEBUG_RAL_ISR_TRACE */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_STOP_OPRTN == 1)
|
||||
RT_DEBUG_RAL_STOP_OPRTN,
|
||||
#endif /* USE_RT_DEBUG_RAL_STOP_OPRTN */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_STRT_RX == 1)
|
||||
RT_DEBUG_RAL_STRT_RX,
|
||||
#endif /* USE_RT_DEBUG_RAL_STRT_RX */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_DONE_CLBK_TX == 1)
|
||||
RT_DEBUG_RAL_DONE_CLBK_TX,
|
||||
#endif /* USE_RT_DEBUG_RAL_DONE_CLBK_TX */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_DONE_CLBK_RX == 1)
|
||||
RT_DEBUG_RAL_DONE_CLBK_RX,
|
||||
#endif /* USE_RT_DEBUG_RAL_DONE_CLBK_RX */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_DONE_CLBK_ED == 1)
|
||||
RT_DEBUG_RAL_DONE_CLBK_ED,
|
||||
#endif /* USE_RT_DEBUG_RAL_DONE_CLBK_ED */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_ED_SCAN == 1)
|
||||
RT_DEBUG_RAL_ED_SCAN,
|
||||
#endif /* USE_RT_DEBUG_RAL_ED_SCAN */
|
||||
|
||||
#if (USE_RT_DEBUG_ERROR_MEM_CAP_EXCED == 1)
|
||||
RT_DEBUG_ERROR_MEM_CAP_EXCED,
|
||||
#endif /* USE_RT_DEBUG_ERROR_MEM_CAP_EXCED */
|
||||
|
||||
#if (USE_RT_DEBUG_ERROR_COMMAND_DISALLOWED == 1)
|
||||
RT_DEBUG_ERROR_COMMAND_DISALLOWED,
|
||||
#endif /* USE_RT_DEBUG_ERROR_COMMAND_DISALLOWED */
|
||||
|
||||
#if (USE_RT_DEBUG_PTA_INIT == 1)
|
||||
RT_DEBUG_PTA_INIT,
|
||||
#endif /* USE_RT_DEBUG_PTA_INIT */
|
||||
|
||||
#if (USE_RT_DEBUG_PTA_EN == 1)
|
||||
RT_DEBUG_PTA_EN,
|
||||
#endif /* USE_RT_DEBUG_PTA_EN */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_PTA_SET_EN == 1)
|
||||
RT_DEBUG_LLHWC_PTA_SET_EN,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_PTA_SET_EN */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_PTA_SET_PARAMS == 1)
|
||||
RT_DEBUG_LLHWC_PTA_SET_PARAMS,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_PTA_SET_PARAMS */
|
||||
|
||||
#if (USE_RT_DEBUG_COEX_STRT_ON_IDLE == 1)
|
||||
RT_DEBUG_COEX_STRT_ON_IDLE,
|
||||
#endif /* USE_RT_DEBUG_COEX_STRT_ON_IDLE */
|
||||
|
||||
#if (USE_RT_DEBUG_COEX_ASK_FOR_AIR == 1)
|
||||
RT_DEBUG_COEX_ASK_FOR_AIR,
|
||||
#endif /* USE_RT_DEBUG_COEX_ASK_FOR_AIR */
|
||||
|
||||
#if (USE_RT_DEBUG_COEX_TIMER_EVNT_CLBK == 1)
|
||||
RT_DEBUG_COEX_TIMER_EVNT_CLBK,
|
||||
#endif /* USE_RT_DEBUG_COEX_TIMER_EVNT_CLBK */
|
||||
|
||||
#if (USE_RT_DEBUG_COEX_STRT_ONE_SHOT == 1)
|
||||
RT_DEBUG_COEX_STRT_ONE_SHOT,
|
||||
#endif /* USE_RT_DEBUG_COEX_STRT_ONE_SHOT */
|
||||
|
||||
#if (USE_RT_DEBUG_COEX_FORCE_STOP_RX == 1)
|
||||
RT_DEBUG_COEX_FORCE_STOP_RX,
|
||||
#endif /* USE_RT_DEBUG_COEX_FORCE_STOP_RX */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_ADV_DONE == 1)
|
||||
RT_DEBUG_LLHWC_ADV_DONE,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_ADV_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_SCN_DONE == 1)
|
||||
RT_DEBUG_LLHWC_SCN_DONE,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_SCN_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_INIT_DONE == 1)
|
||||
RT_DEBUG_LLHWC_INIT_DONE,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_INIT_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_CONN_DONE == 1)
|
||||
RT_DEBUG_LLHWC_CONN_DONE,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_CONN_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_CIG_DONE == 1)
|
||||
RT_DEBUG_LLHWC_CIG_DONE,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_CIG_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_BIG_DONE == 1)
|
||||
RT_DEBUG_LLHWC_BIG_DONE,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_BIG_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_OS_TMR_CREATE == 1)
|
||||
RT_DEBUG_OS_TMR_CREATE,
|
||||
#endif /* USE_RT_DEBUG_OS_TMR_CREATE */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_TIMEOUT_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_TIMEOUT_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_TIMEOUT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_SCN_DUR_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_SCN_DUR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_SCN_DUR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_SCN_PERIOD_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_SCN_PERIOD_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_SCN_PERIOD_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_PRDC_SCN_TIMEOUT_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_PRDC_SCN_TIMEOUT_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_PRDC_SCN_TIMEOUT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIS_SYNC_TIMEOUT_TMR_CBK == 1)
|
||||
RT_DEBUG_BIS_SYNC_TIMEOUT_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIS_SYNC_TIMEOUT_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIS_TERM_TMR_CBK == 1)
|
||||
RT_DEBUG_BIS_TERM_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIS_TERM_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIS_TST_MODE_CBK == 1)
|
||||
RT_DEBUG_BIS_TST_MODE_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIS_TST_MODE_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIS_TST_MODE_TMR_CBK == 1)
|
||||
RT_DEBUG_BIS_TST_MODE_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIS_TST_MODE_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ISO_POST_TMR_CBK == 1)
|
||||
RT_DEBUG_ISO_POST_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ISO_POST_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ISO_TST_MODE_TMR_CBK == 1)
|
||||
RT_DEBUG_ISO_TST_MODE_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ISO_TST_MODE_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_CONN_POST_TMR_CBK == 1)
|
||||
RT_DEBUG_CONN_POST_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_CONN_POST_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_EVNT_SCHDLR_TMR_CBK == 1)
|
||||
RT_DEBUG_EVNT_SCHDLR_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_EVNT_SCHDLR_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_HCI_POST_TMR_CBK == 1)
|
||||
RT_DEBUG_HCI_POST_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_HCI_POST_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_LLCP_POST_TMR_CBK == 1)
|
||||
RT_DEBUG_LLCP_POST_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_LLCP_POST_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_ENRGY_DETECT_CBK == 1)
|
||||
RT_DEBUG_LLHWC_ENRGY_DETECT_CBK,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_ENRGY_DETECT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_PRVCY_POST_TMR_CBK == 1)
|
||||
RT_DEBUG_PRVCY_POST_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_PRVCY_POST_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ANT_PRPR_TMR_CBK == 1)
|
||||
RT_DEBUG_ANT_PRPR_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ANT_PRPR_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_COEX_TMR_FRC_STOP_AIR_GRANT_CBK == 1)
|
||||
RT_DEBUG_COEX_TMR_FRC_STOP_AIR_GRANT_CBK,
|
||||
#endif /* USE_RT_DEBUG_COEX_TMR_FRC_STOP_AIR_GRANT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_MLME_RX_EN_TMR_CBK == 1)
|
||||
RT_DEBUG_MLME_RX_EN_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_MLME_RX_EN_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_MLME_GNRC_TMR_CBK == 1)
|
||||
RT_DEBUG_MLME_GNRC_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_MLME_GNRC_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_MIB_JOIN_LST_TMR_CBK == 1)
|
||||
RT_DEBUG_MIB_JOIN_LST_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_MIB_JOIN_LST_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_MLME_PWR_PRES_TMR_CBK == 1)
|
||||
RT_DEBUG_MLME_PWR_PRES_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_MLME_PWR_PRES_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_PRESISTENCE_TMR_CBK == 1)
|
||||
RT_DEBUG_PRESISTENCE_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_PRESISTENCE_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_RADIO_PHY_PRDC_CLBK_TMR_CBK == 1)
|
||||
RT_DEBUG_RADIO_PHY_PRDC_CLBK_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_RADIO_PHY_PRDC_CLBK_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_RADIO_CSMA_TMR_CBK == 1)
|
||||
RT_DEBUG_RADIO_CSMA_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_RADIO_CSMA_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_RADIO_CSL_RCV_TMR_CBK == 1)
|
||||
RT_DEBUG_RADIO_CSL_RCV_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_RADIO_CSL_RCV_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ED_TMR_CBK == 1)
|
||||
RT_DEBUG_ED_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ED_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_DIO_EXT_TMR_CBK == 1)
|
||||
RT_DEBUG_DIO_EXT_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_DIO_EXT_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_RCO_CLBR_TMR_CBK == 1)
|
||||
RT_DEBUG_RCO_CLBR_TMR_CBK,
|
||||
#endif /* USE_RT_DEBUG_RCO_CLBR_TMR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_ADV_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_ADV_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_ADV_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_SCN_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_ERR_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_SCN_ERR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_ERR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_ERR_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_ERR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_ERR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIG_ADV_CBK == 1)
|
||||
RT_DEBUG_BIG_ADV_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIG_ADV_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIG_ADV_ERR_CBK == 1)
|
||||
RT_DEBUG_BIG_ADV_ERR_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIG_ADV_ERR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIG_SYNC_CBK == 1)
|
||||
RT_DEBUG_BIG_SYNC_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIG_SYNC_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIG_SYNC_ERR_CBK == 1)
|
||||
RT_DEBUG_BIG_SYNC_ERR_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIG_SYNC_ERR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ISO_CIS_PKT_TRNSM_RECEIVED_CBK == 1)
|
||||
RT_DEBUG_ISO_CIS_PKT_TRNSM_RECEIVED_CBK,
|
||||
#endif /* USE_RT_DEBUG_ISO_CIS_PKT_TRNSM_RECEIVED_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ISO_CIG_ERR_CBK == 1)
|
||||
RT_DEBUG_ISO_CIG_ERR_CBK,
|
||||
#endif /* USE_RT_DEBUG_ISO_CIG_ERR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_CONN_PKT_TRNSM_RECEIVED_CBK == 1)
|
||||
RT_DEBUG_CONN_PKT_TRNSM_RECEIVED_CBK,
|
||||
#endif /* USE_RT_DEBUG_CONN_PKT_TRNSM_RECEIVED_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_PRDC_CLBR_EXTRL_CBK == 1)
|
||||
RT_DEBUG_PRDC_CLBR_EXTRL_CBK,
|
||||
#endif /* USE_RT_DEBUG_PRDC_CLBR_EXTRL_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_PTR_PRDC_ADV_SYNC_CBK == 1)
|
||||
RT_DEBUG_PTR_PRDC_ADV_SYNC_CBK,
|
||||
#endif /* USE_RT_DEBUG_PTR_PRDC_ADV_SYNC_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_NCONN_SCN_CBK == 1)
|
||||
RT_DEBUG_NCONN_SCN_CBK,
|
||||
#endif /* USE_RT_DEBUG_NCONN_SCN_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_NCONN_ADV_CBK == 1)
|
||||
RT_DEBUG_NCONN_ADV_CBK,
|
||||
#endif /* USE_RT_DEBUG_NCONN_ADV_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_NCONN_INIT_CBK == 1)
|
||||
RT_DEBUG_NCONN_INIT_CBK,
|
||||
#endif /* USE_RT_DEBUG_NCONN_INIT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ANT_RADIO_CMPLT_EVNT_CBK == 1)
|
||||
RT_DEBUG_ANT_RADIO_CMPLT_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_ANT_RADIO_CMPLT_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ANT_STACK_EVNT_CBK == 1)
|
||||
RT_DEBUG_ANT_STACK_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_ANT_STACK_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_PROCESS_TMOUT_EVNT_CBK == 1)
|
||||
RT_DEBUG_ADV_EXT_PROCESS_TMOUT_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_PROCESS_TMOUT_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_DUR_EVNT == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_SCN_DUR_EVNT,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_DUR_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_PERIODIC_EVNT == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_SCN_PERIODIC_EVNT,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_PERIODIC_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_TMOUT_EVNT == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_TMOUT_EVNT,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_TMOUT_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CNCEL_EVNT == 1)
|
||||
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CNCEL_EVNT,
|
||||
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CNCEL_EVNT */
|
||||
|
||||
#if (USE_RT_DEBUG_BIS_MNGR_BIG_TERM_CBK == 1)
|
||||
RT_DEBUG_BIS_MNGR_BIG_TERM_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIS_MNGR_BIG_TERM_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_BIS_MNGR_SYNC_TMOUT_CBK == 1)
|
||||
RT_DEBUG_BIS_MNGR_SYNC_TMOUT_CBK,
|
||||
#endif /* USE_RT_DEBUG_BIS_MNGR_SYNC_TMOUT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ISOAL_MNGR_SDU_GEN == 1)
|
||||
RT_DEBUG_ISOAL_MNGR_SDU_GEN,
|
||||
#endif /* USE_RT_DEBUG_ISOAL_MNGR_SDU_GEN */
|
||||
|
||||
#if (USE_RT_DEBUG_ISO_MNGR_CIS_PROCESS_EVNT_CBK == 1)
|
||||
RT_DEBUG_ISO_MNGR_CIS_PROCESS_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_ISO_MNGR_CIS_PROCESS_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_CONN_MNGR_PROCESS_EVNT_CLBK == 1)
|
||||
RT_DEBUG_CONN_MNGR_PROCESS_EVNT_CLBK,
|
||||
#endif /* USE_RT_DEBUG_CONN_MNGR_PROCESS_EVNT_CLBK */
|
||||
|
||||
#if (USE_RT_DEBUG_CONN_MNGR_UPDT_CONN_PARAM_CBK == 1)
|
||||
RT_DEBUG_CONN_MNGR_UPDT_CONN_PARAM_CBK,
|
||||
#endif /* USE_RT_DEBUG_CONN_MNGR_UPDT_CONN_PARAM_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_EVNT_SCHDLR_HW_EVNT_CMPLT == 1)
|
||||
RT_DEBUG_EVNT_SCHDLR_HW_EVNT_CMPLT,
|
||||
#endif /* USE_RT_DEBUG_EVNT_SCHDLR_HW_EVNT_CMPLT */
|
||||
|
||||
#if (USE_RT_DEBUG_HCI_EVENT_HNDLR == 1)
|
||||
RT_DEBUG_HCI_EVENT_HNDLR,
|
||||
#endif /* USE_RT_DEBUG_HCI_EVENT_HNDLR */
|
||||
|
||||
#if (USE_RT_DEBUG_MLME_TMRS_CBK == 1)
|
||||
RT_DEBUG_MLME_TMRS_CBK,
|
||||
#endif /* USE_RT_DEBUG_MLME_TMRS_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_DIRECT_TX_EVNT_CBK == 1)
|
||||
RT_DEBUG_DIRECT_TX_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_DIRECT_TX_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_INDIRECT_PKT_TOUR_CBK == 1)
|
||||
RT_DEBUG_INDIRECT_PKT_TOUR_CBK,
|
||||
#endif /* USE_RT_DEBUG_INDIRECT_PKT_TOUR_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_RADIO_CSMA_TMR == 1)
|
||||
RT_DEBUG_RADIO_CSMA_TMR,
|
||||
#endif /* USE_RT_DEBUG_RADIO_CSMA_TMR */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_SM_DONE_EVNT_CBK == 1)
|
||||
RT_DEBUG_RAL_SM_DONE_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_RAL_SM_DONE_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_ED_TMR_HNDL == 1)
|
||||
RT_DEBUG_ED_TMR_HNDL,
|
||||
#endif /* USE_RT_DEBUG_ED_TMR_HNDL */
|
||||
|
||||
#if (USE_RT_DEBUG_OS_TMR_EVNT_CBK == 1)
|
||||
RT_DEBUG_OS_TMR_EVNT_CBK,
|
||||
#endif /* USE_RT_DEBUG_OS_TMR_EVNT_CBK */
|
||||
|
||||
#if (USE_RT_DEBUG_PROFILE_MARKER_PHY_WAKEUP_TIME == 1)
|
||||
RT_DEBUG_PROFILE_MARKER_PHY_WAKEUP_TIME,
|
||||
#endif /* USE_RT_DEBUG_PROFILE_MARKER_PHY_WAKEUP_TIME */
|
||||
|
||||
#if (USE_RT_DEBUG_PROFILE_END_DRIFT_TIME == 1)
|
||||
RT_DEBUG_PROFILE_END_DRIFT_TIME,
|
||||
#endif /* USE_RT_DEBUG_PROFILE_END_DRIFT_TIME */
|
||||
|
||||
#if (USE_RT_DEBUG_PROC_RADIO_RCV == 1)
|
||||
RT_DEBUG_PROC_RADIO_RCV,
|
||||
#endif /* USE_RT_DEBUG_PROC_RADIO_RCV */
|
||||
|
||||
#if (USE_RT_DEBUG_EVNT_TIME_UPDT == 1)
|
||||
RT_DEBUG_EVNT_TIME_UPDT,
|
||||
#endif /* USE_RT_DEBUG_EVNT_TIME_UPDT */
|
||||
|
||||
#if (USE_RT_DEBUG_MAC_RECEIVE_DONE == 1)
|
||||
RT_DEBUG_MAC_RECEIVE_DONE,
|
||||
#endif /* USE_RT_DEBUG_MAC_RECEIVE_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_MAC_TX_DONE == 1)
|
||||
RT_DEBUG_MAC_TX_DONE,
|
||||
#endif /* USE_RT_DEBUG_MAC_TX_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_RADIO_APPLY_CSMA == 1)
|
||||
RT_DEBUG_RADIO_APPLY_CSMA,
|
||||
#endif /* USE_RT_DEBUG_RADIO_APPLY_CSMA */
|
||||
|
||||
#if (USE_RT_DEBUG_RADIO_TRANSMIT == 1)
|
||||
RT_DEBUG_RADIO_TRANSMIT,
|
||||
#endif /* USE_RT_DEBUG_RADIO_TRANSMIT */
|
||||
|
||||
#if (USE_RT_DEBUG_PROC_RADIO_TX == 1)
|
||||
RT_DEBUG_PROC_RADIO_TX,
|
||||
#endif /* USE_RT_DEBUG_PROC_RADIO_TX */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_TX_DONE == 1)
|
||||
RT_DEBUG_RAL_TX_DONE,
|
||||
#endif /* USE_RT_DEBUG_RAL_TX_DONE */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_TX_DONE_INCREMENT_BACKOFF_COUNT == 1)
|
||||
RT_DEBUG_RAL_TX_DONE_INCREMENT_BACKOFF_COUNT,
|
||||
#endif /* USE_RT_DEBUG_RAL_TX_DONE_INCREMENT_BACKOFF_COUNT */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_TX_DONE_RST_BACKOFF_COUNT == 1)
|
||||
RT_DEBUG_RAL_TX_DONE_RST_BACKOFF_COUNT,
|
||||
#endif /* USE_RT_DEBUG_RAL_TX_DONE_RST_BACKOFF_COUNT */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_CONTINUE_RX == 1)
|
||||
RT_DEBUG_RAL_CONTINUE_RX,
|
||||
#endif /* USE_RT_DEBUG_RAL_CONTINUE_RX */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_PERFORM_CCA == 1)
|
||||
RT_DEBUG_RAL_PERFORM_CCA,
|
||||
#endif /* USE_RT_DEBUG_RAL_PERFORM_CCA */
|
||||
|
||||
#if (USE_RT_DEBUG_RAL_ENABLE_TRANSMITTER == 1)
|
||||
RT_DEBUG_RAL_ENABLE_TRANSMITTER,
|
||||
#endif /* USE_RT_DEBUG_RAL_ENABLE_TRANSMITTER */
|
||||
|
||||
#if (USE_RT_DEBUG_LLHWC_GET_CH_IDX_ALGO_2 == 1)
|
||||
RT_DEBUG_LLHWC_GET_CH_IDX_ALGO_2,
|
||||
#endif /* USE_RT_DEBUG_LLHWC_GET_CH_IDX_ALGO_2 */
|
||||
|
||||
#if (USE_RT_DEBUG_BACK_FROM_DEEP_SLEEP == 1)
|
||||
RT_DEBUG_BACK_FROM_DEEP_SLEEP,
|
||||
#endif /* USE_RT_DEBUG_BACK_FROM_DEEP_SLEEP */
|
||||
|
||||
#include "app_debug_signal_def.h"
|
||||
|
||||
RT_DEBUG_SIGNALS_TOTAL_NUM
|
||||
} rt_debug_signal_t;
|
||||
|
||||
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DEBUG_SIGNALS_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file serial_cmd_interpreter.c
|
||||
* @author MCD Application Team
|
||||
* @brief Source file for the serial commands interpreter module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "log_module.h"
|
||||
#include "app_conf.h"
|
||||
#include "stm32_adv_trace.h"
|
||||
#include "serial_cmd_interpreter.h"
|
||||
|
||||
/* Private includes -----------------------------------------------------------*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define RX_BUFF_SIZE (256U)
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
static uint8_t RxBuffer[RX_BUFF_SIZE];
|
||||
static uint16_t indexRxBuffer = 0;
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
|
||||
/* Private functions prototypes ----------------------------------------------*/
|
||||
static void UART_Rx_Callback(uint8_t *PData, uint16_t Size, uint8_t Error);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void Serial_CMD_Interpreter_Init(void)
|
||||
{
|
||||
/* Init Communication reception. Need that Log/Traces are activated */
|
||||
UTIL_ADV_TRACE_StartRxProcess(UART_Rx_Callback);
|
||||
}
|
||||
|
||||
__weak void Serial_CMD_Interpreter_CmdExecute( uint8_t * pRxBuffer, uint16_t iRxBufferSize )
|
||||
{
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the enter_standby_notification could be implemented in the user file
|
||||
*/
|
||||
|
||||
/*
|
||||
This user function is in charge of interpreting the received data.
|
||||
|
||||
Here is an example of how to use them.
|
||||
In this simple case, we'll generate a SW IT on GPIO14 if the received data is a string "TEST".
|
||||
Add the following code into the user code section :
|
||||
|
||||
// Extended line handler on which we will generate the IT
|
||||
EXTI_HandleTypeDef exti_handle;
|
||||
|
||||
// Check RxBuffer's content to know if we're matching our case
|
||||
if( strcmp( (char const*)pRxBuffer, "TEST" ) == 0 )
|
||||
{
|
||||
LOG_INFO_APP("TEST has been received in Uart_Cmd_Execute.\n");
|
||||
exti_handle.Line = EXTI_LINE_14;
|
||||
HAL_EXTI_GenerateSWI(&exti_handle);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* Private functions definition ----------------------------------------------*/
|
||||
static void UART_Rx_Callback( uint8_t * pData, uint16_t Size, uint8_t Error )
|
||||
{
|
||||
/* Filling buffer and wait for '\r' charactere to execute actions */
|
||||
if ( indexRxBuffer < RX_BUFF_SIZE )
|
||||
{
|
||||
if ( *pData == '\r' )
|
||||
{
|
||||
Serial_CMD_Interpreter_CmdExecute( RxBuffer, indexRxBuffer );
|
||||
|
||||
/* Clear receive buffer and character counter*/
|
||||
indexRxBuffer = 0;
|
||||
memset( &RxBuffer[0], 0, RX_BUFF_SIZE );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( * pData == '\n' ) && ( indexRxBuffer == 0 ) )
|
||||
{
|
||||
/* discard this first charactere if it's a delimiter */
|
||||
}
|
||||
else
|
||||
{
|
||||
RxBuffer[indexRxBuffer++] = *pData;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indexRxBuffer = 0;
|
||||
memset(&RxBuffer[0], 0, RX_BUFF_SIZE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file serial_cmd_interpreter.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file for the serial commands interpreter module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SERIAL_CMD_INTERPRETER_H
|
||||
#define SERIAL_CMD_INTERPRETER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Serial_CMD_Interpreter_Init(void);
|
||||
void Serial_CMD_Interpreter_CmdExecute( uint8_t * pRxBuffer, uint16_t iRxBufferSize );
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SERIAL_CMD_INTERPRETER_H */
|
||||
@@ -0,0 +1,892 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file adc_ctrl.c
|
||||
* @author MCD Application Team
|
||||
* @brief Source file for ADC controller module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* Utilities */
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Real time trace for debug */
|
||||
#include "RTDebug.h"
|
||||
|
||||
/* Own header files */
|
||||
#include "adc_ctrl.h"
|
||||
#include "adc_ctrl_conf.h"
|
||||
|
||||
/* LL ADC header */
|
||||
#include "stm32wbaxx_ll_adc.h"
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initial value define for configuration tracking number
|
||||
*/
|
||||
#define ADCCTRL_NO_CONFIG (uint32_t)(0x00000000u)
|
||||
|
||||
/**
|
||||
* @brief Init variable out of expected ADC conversion data range
|
||||
*/
|
||||
#define VAR_CONVERTED_DATA_INIT_VALUE_12B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B) + 1)
|
||||
#define VAR_CONVERTED_DATA_INIT_VALUE_10B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_10B) + 1)
|
||||
#define VAR_CONVERTED_DATA_INIT_VALUE_8B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_8B) + 1)
|
||||
#define VAR_CONVERTED_DATA_INIT_VALUE_6B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_6B) + 1)
|
||||
|
||||
/**
|
||||
* @brief Internal temperature sensor, parameter V30 (unit: mV).
|
||||
*
|
||||
* @details Refer to device datasheet for min/typ/max values.
|
||||
*
|
||||
*/
|
||||
#define TEMPSENSOR_TYP_CAL1_V (( int32_t) 760)
|
||||
|
||||
/**
|
||||
* @brief Internal temperature sensor, parameter Avg_Slope (unit: uV/DegCelsius).
|
||||
*
|
||||
* @details Refer to device datasheet for min/typ/max values.
|
||||
*
|
||||
*/
|
||||
#define TEMPSENSOR_TYP_AVGSLOPE (( int32_t) 2500)
|
||||
|
||||
/* Definitions of environment analog values */
|
||||
/**
|
||||
* @brief Value of analog reference voltage (Vref+), connected to analog voltage
|
||||
*
|
||||
* @details supply Vdda (unit: mV).
|
||||
*
|
||||
*/
|
||||
#define VDDA_APPLI (3300UL)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC IP Client list
|
||||
*/
|
||||
static uint32_t ClientList;
|
||||
|
||||
/**
|
||||
* @brief Tracker of the current applied configuration
|
||||
*/
|
||||
static uint32_t CurrentConfig = ADCCTRL_NO_CONFIG;
|
||||
|
||||
/**
|
||||
* @brief Higher registered handle ID
|
||||
*/
|
||||
static uint32_t MaxRegisteredId = ADCCTRL_NO_CONFIG;
|
||||
|
||||
/**
|
||||
* @brief Handle of the ADC
|
||||
*/
|
||||
static ADC_TypeDef * p_ADCHandle = ADCCTRL_HWADDR;
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Error Handler */
|
||||
extern void Error_Handler(void);
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/**
|
||||
* @brief Activate ADC.
|
||||
* Activation order is as follow:
|
||||
* - Enable ADC peripharal clock
|
||||
* - Enable ADC internal voltage regulator
|
||||
* - Enable ADC
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static inline void AdcActivate (void);
|
||||
|
||||
/**
|
||||
* @brief Deactivate ADC IP.
|
||||
* Deactivation order is as follow:
|
||||
* - Disable ADC
|
||||
* - Disable ADC internal voltage regulator
|
||||
* - Disable ADC peripharal clock
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static inline void AdcDeactivate (void);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC IP.
|
||||
* @param p_Handle: Handle to work with
|
||||
* @retval State of the configuration
|
||||
*/
|
||||
static inline ADCCTRL_Cmd_Status_t AdcConfigure (const ADCCTRL_Handle_t * const p_Handle);
|
||||
|
||||
/**
|
||||
* @brief Read the raw value
|
||||
* @param p_Handle: Handle to work with
|
||||
* @return Raw value
|
||||
*/
|
||||
static inline uint16_t AdcReadRaw (const ADCCTRL_Handle_t * const p_Handle);
|
||||
|
||||
/**
|
||||
* @brief Perform ADC group regular conversion start, poll for conversion
|
||||
* completion.
|
||||
* (ADCCTRL_HWADDR instance: ADC).
|
||||
* @note This function does not perform ADC group regular conversion stop:
|
||||
* intended to be used with ADC in single mode, trigger SW start
|
||||
* (only 1 ADC conversion done at each trigger, no conversion stop
|
||||
* needed).
|
||||
* In case of continuous mode or conversion trigger set to
|
||||
* external trigger, ADC group regular conversion stop must be added.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static inline void ConversionStartPoll_ADC_GrpRegular (void);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_Init (void)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
/* Try to take the ADC mutex */
|
||||
error = ADCCTRL_MutexTake ();
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
CurrentConfig = ADCCTRL_NO_CONFIG;
|
||||
|
||||
p_ADCHandle = ADCCTRL_HWADDR;
|
||||
|
||||
/* Reset ADC Client list */
|
||||
ClientList = 0x00u;
|
||||
|
||||
/* Deactivate the ADC */
|
||||
AdcDeactivate();
|
||||
|
||||
/* Release the mutex */
|
||||
ADCCTRL_MutexRelease ();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RegisterHandle (ADCCTRL_Handle_t * const p_Handle)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
if (NULL == p_Handle)
|
||||
{
|
||||
error = ADCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
else if (ADCCTRL_HANDLE_REG == p_Handle->State)
|
||||
{
|
||||
error = ADCCTRL_HANDLE_ALREADY_REGISTERED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the ADC mutex */
|
||||
error = ADCCTRL_MutexTake ();
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Update the maximum registered handle */
|
||||
MaxRegisteredId = MaxRegisteredId + 1u;
|
||||
/* Update the handle UUID */
|
||||
p_Handle->Uid = MaxRegisteredId;
|
||||
/* Set handle as initialized */
|
||||
p_Handle->State = ADCCTRL_HANDLE_REG;
|
||||
|
||||
/* Release the mutex */
|
||||
ADCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestIpState (const ADCCTRL_Handle_t * const p_Handle,
|
||||
const ADCCTRL_Ip_State_t State)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
if (ADC_OFF == State)
|
||||
{
|
||||
ClientList &= (~(1U << p_Handle->Uid));
|
||||
|
||||
error = ADCCTRL_OK;
|
||||
}
|
||||
else if (ADC_ON == State)
|
||||
{
|
||||
ClientList |= (1U << p_Handle->Uid);
|
||||
|
||||
error = ADCCTRL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ADCCTRL_ERROR_STATE;
|
||||
}
|
||||
|
||||
if (0x00u == ClientList)
|
||||
{
|
||||
/* Disable ADC as there is no request anymore */
|
||||
AdcDeactivate();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable ADC as there at least one request */
|
||||
AdcActivate();
|
||||
}
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestRawValue (const ADCCTRL_Handle_t * const p_Handle,
|
||||
uint16_t * const p_ReadValue)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
/* Null pointer for handle or payload */
|
||||
if ((NULL == p_Handle) || (NULL == p_ReadValue))
|
||||
{
|
||||
error = ADCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
/* Handle not init */
|
||||
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_REGISTERED;
|
||||
}
|
||||
/* Handle not in the range */
|
||||
else if ((MaxRegisteredId < p_Handle->Uid) ||
|
||||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_VALID;
|
||||
}
|
||||
/* Check ADC state */
|
||||
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
|
||||
{
|
||||
error = ADCCTRL_ERROR_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the ADC mutex */
|
||||
error = ADCCTRL_MutexTake ();
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Is the current config IS NOT the same as the one requested ? */
|
||||
if (CurrentConfig != p_Handle->Uid)
|
||||
{
|
||||
/* Configure the ADC before use */
|
||||
error = AdcConfigure (p_Handle);
|
||||
|
||||
/* Enable ADC */
|
||||
LL_ADC_Enable(p_ADCHandle);
|
||||
}
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Return the read value */
|
||||
*p_ReadValue = AdcReadRaw (p_Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ADCCTRL_ERROR_CONFIG;
|
||||
}
|
||||
|
||||
/* Release the mutex */
|
||||
ADCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestTemperature (const ADCCTRL_Handle_t * const p_Handle,
|
||||
int16_t * const p_ReadValue)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
/* Variables for ADC conversion data */
|
||||
__IO uint16_t uhADCxConvertedData = 0x00;
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_SET(ADC_TEMPERATURE_ACQUISITION);
|
||||
|
||||
/* Null pointer for handle or payload */
|
||||
if ((NULL == p_Handle) || (NULL == p_ReadValue))
|
||||
{
|
||||
error = ADCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
/* Handle not init */
|
||||
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_REGISTERED;
|
||||
}
|
||||
/* Handle not in the range */
|
||||
else if ((MaxRegisteredId < p_Handle->Uid) ||
|
||||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_VALID;
|
||||
}
|
||||
/* Check ADC state */
|
||||
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
|
||||
{
|
||||
error = ADCCTRL_ERROR_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the ADC mutex */
|
||||
error = ADCCTRL_MutexTake ();
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Is the current config IS NOT the same as the one requested ? */
|
||||
if (CurrentConfig != p_Handle->Uid)
|
||||
{
|
||||
/* Configure the ADC before use */
|
||||
error = AdcConfigure (p_Handle);
|
||||
|
||||
/* Enable ADC */
|
||||
LL_ADC_Enable(p_ADCHandle);
|
||||
}
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Return the read value */
|
||||
uhADCxConvertedData = AdcReadRaw (p_Handle);
|
||||
|
||||
/* Computation of ADC conversions raw data to physical values */
|
||||
/* using LL ADC driver helper macro. */
|
||||
if(*TEMPSENSOR_CAL1_ADDR == *TEMPSENSOR_CAL2_ADDR)
|
||||
{
|
||||
/* Case of samples not calibrated in production */
|
||||
*p_ReadValue = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS (TEMPSENSOR_TYP_AVGSLOPE,
|
||||
TEMPSENSOR_TYP_CAL1_V,
|
||||
TEMPSENSOR_CAL1_TEMP,
|
||||
VDDA_APPLI,
|
||||
uhADCxConvertedData,
|
||||
p_Handle->InitConf.ConvParams.Resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Case of samples calibrated in production */
|
||||
*p_ReadValue = __LL_ADC_CALC_TEMPERATURE (VDDA_APPLI,
|
||||
uhADCxConvertedData,
|
||||
p_Handle->InitConf.ConvParams.Resolution);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ADCCTRL_ERROR_CONFIG;
|
||||
}
|
||||
|
||||
/* Release the mutex */
|
||||
ADCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestCoreVoltage (const ADCCTRL_Handle_t * const p_Handle,
|
||||
uint16_t * const p_ReadValue)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
/* Variables for ADC conversion data */
|
||||
__IO uint16_t uhADCxConvertedData = 0x00;
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_SET(ADC_TEMPERATURE_ACQUISITION);
|
||||
|
||||
/* Null pointer for handle or payload */
|
||||
if ((NULL == p_Handle) || (NULL == p_ReadValue))
|
||||
{
|
||||
error = ADCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
/* Handle not init */
|
||||
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_REGISTERED;
|
||||
}
|
||||
/* Handle not in the range */
|
||||
else if ((MaxRegisteredId < p_Handle->Uid) ||
|
||||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_VALID;
|
||||
}
|
||||
/* Check ADC state */
|
||||
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
|
||||
{
|
||||
error = ADCCTRL_ERROR_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the ADC mutex */
|
||||
error = ADCCTRL_MutexTake ();
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Is the current config IS NOT the same as the one requested ? */
|
||||
if (CurrentConfig != p_Handle->Uid)
|
||||
{
|
||||
/* Configure the ADC before use */
|
||||
error = AdcConfigure (p_Handle);
|
||||
|
||||
/* Enable ADC */
|
||||
LL_ADC_Enable(p_ADCHandle);
|
||||
}
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Return the read value */
|
||||
uhADCxConvertedData = AdcReadRaw (p_Handle);
|
||||
|
||||
/* Computation of ADC conversions raw data to physical values */
|
||||
/* using LL ADC driver helper macro. */
|
||||
*p_ReadValue = __LL_ADC_CALC_DATA_TO_VOLTAGE (VDDA_APPLI,
|
||||
uhADCxConvertedData,
|
||||
p_Handle->InitConf.ConvParams.Resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ADCCTRL_ERROR_CONFIG;
|
||||
}
|
||||
|
||||
/* Release the mutex */
|
||||
ADCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestRefVoltage (const ADCCTRL_Handle_t * const p_Handle,
|
||||
uint16_t * const p_ReadValue)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
|
||||
|
||||
/* Variables for ADC conversion data */
|
||||
__IO uint16_t uhADCxConvertedData = 0x00;
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_SET(ADC_TEMPERATURE_ACQUISITION);
|
||||
|
||||
/* Null pointer for handle or payload */
|
||||
if ((NULL == p_Handle) || (NULL == p_ReadValue))
|
||||
{
|
||||
error = ADCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
/* Handle not init */
|
||||
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_REGISTERED;
|
||||
}
|
||||
/* Handle not in the range */
|
||||
else if ((MaxRegisteredId < p_Handle->Uid) ||
|
||||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
|
||||
{
|
||||
error = ADCCTRL_HANDLE_NOT_VALID;
|
||||
}
|
||||
/* Check ADC state */
|
||||
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
|
||||
{
|
||||
error = ADCCTRL_ERROR_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the ADC mutex */
|
||||
error = ADCCTRL_MutexTake ();
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Is the current config IS NOT the same as the one requested ? */
|
||||
if (CurrentConfig != p_Handle->Uid)
|
||||
{
|
||||
/* Configure the ADC before use */
|
||||
error = AdcConfigure (p_Handle);
|
||||
|
||||
/* Enable ADC */
|
||||
LL_ADC_Enable(p_ADCHandle);
|
||||
}
|
||||
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Return the read value */
|
||||
uhADCxConvertedData = AdcReadRaw (p_Handle);
|
||||
|
||||
/* Computation of ADC conversions raw data to physical values */
|
||||
/* using LL ADC driver helper macro. */
|
||||
*p_ReadValue = __LL_ADC_CALC_VREFANALOG_VOLTAGE (uhADCxConvertedData,
|
||||
p_Handle->InitConf.ConvParams.Resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ADCCTRL_ERROR_CONFIG;
|
||||
}
|
||||
|
||||
/* Release the mutex */
|
||||
ADCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Private function Definition -----------------------------------------------*/
|
||||
void AdcActivate (void)
|
||||
{
|
||||
__IO uint32_t backup_setting_adc_dma_transfer = 0U;
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_SET(ADC_ACTIVATION);
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
/*## Operation on ADC hierarchical scope: ADC instance #####################*/
|
||||
|
||||
/* Note: Hardware constraint (refer to description of the functions */
|
||||
/* below): */
|
||||
/* On this STM32 series, setting of these features is conditioned to */
|
||||
/* ADC state: */
|
||||
/* ADC must be disabled. */
|
||||
/* Note: In this example, all these checks are not necessary but are */
|
||||
/* implemented anyway to show the best practice usages */
|
||||
/* corresponding to reference manual procedure. */
|
||||
/* Software can be optimized by removing some of these checks, if */
|
||||
/* they are not relevant considering previous settings and actions */
|
||||
/* in user application. */
|
||||
if (LL_ADC_IsEnabled(p_ADCHandle) == 0)
|
||||
{
|
||||
/* Select clock source */
|
||||
ADCTCTRL_SET_CLOCK_SOURCE ();
|
||||
|
||||
/* Peripheral clock enable */
|
||||
ADCCTRL_ENABLE_CLOCK ();
|
||||
|
||||
/* Enable ADC internal voltage regulator */
|
||||
LL_ADC_EnableInternalRegulator(p_ADCHandle);
|
||||
|
||||
/* Waiting for ADC internal voltage regulator stabilization. */
|
||||
while(LL_ADC_IsInternalRegulatorEnabled(p_ADCHandle) == 0);
|
||||
|
||||
/* Disable ADC DMA transfer request during calibration */
|
||||
/* Note: Specificity of this STM32 series: Calibration factor is */
|
||||
/* available in data register and also transferred by DMA. */
|
||||
/* To not insert ADC calibration factor among ADC conversion data */
|
||||
/* in DMA destination address, DMA transfer must be disabled during */
|
||||
/* calibration. */
|
||||
backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(p_ADCHandle);
|
||||
LL_ADC_REG_SetDMATransfer(p_ADCHandle, LL_ADC_REG_DMA_TRANSFER_NONE);
|
||||
|
||||
/* Run ADC self calibration */
|
||||
LL_ADC_StartCalibration(p_ADCHandle);
|
||||
|
||||
/* Poll for ADC effectively calibrated */
|
||||
while (LL_ADC_IsCalibrationOnGoing(p_ADCHandle) != 0);
|
||||
|
||||
/* Restore ADC DMA transfer request after calibration */
|
||||
LL_ADC_REG_SetDMATransfer(p_ADCHandle, backup_setting_adc_dma_transfer);
|
||||
|
||||
/* Delay required between ADC end of calibration and ADC enable */
|
||||
/* LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES --> 2 cycles */
|
||||
__asm("mov r0, r0");
|
||||
__asm("mov r0, r0");
|
||||
|
||||
/* Enable ADC */
|
||||
LL_ADC_Enable(p_ADCHandle);
|
||||
|
||||
/* Poll for ADC ready to convert */
|
||||
while (LL_ADC_IsActiveFlag_ADRDY(p_ADCHandle) == 0);
|
||||
|
||||
/* Note: ADC flag ADRDY is not cleared here to be able to check ADC */
|
||||
/* status afterwards. */
|
||||
/* This flag should be cleared at ADC Deactivation, before a new */
|
||||
/* ADC activation, using function "LL_ADC_ClearFlag_ADRDY()". */
|
||||
}
|
||||
|
||||
/*## Operation on ADC hierarchical scope: ADC group regular ################*/
|
||||
/* Note: No operation on ADC group regular performed here. */
|
||||
/* ADC group regular conversions to be performed after this function */
|
||||
/* using function: */
|
||||
/* "LL_ADC_REG_StartConversion();" */
|
||||
|
||||
/*## Operation on ADC hierarchical scope: ADC group injected ###############*/
|
||||
/* Note: Feature not available on this STM32 series */
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_RESET(ADC_ACTIVATION);
|
||||
}
|
||||
|
||||
void AdcDeactivate (void)
|
||||
{
|
||||
SYSTEM_DEBUG_SIGNAL_SET(ADC_DEACTIVATION);
|
||||
|
||||
UTILS_ENTER_CRITICAL_SECTION();
|
||||
|
||||
if(LL_ADC_IsEnabled(p_ADCHandle))
|
||||
{
|
||||
/* Disable ADC */
|
||||
LL_ADC_Disable(p_ADCHandle);
|
||||
|
||||
/* Clear flag ADC ready */
|
||||
LL_ADC_ClearFlag_ADRDY(p_ADCHandle);
|
||||
|
||||
/* Wait until ADC_CR_ADEN bit is reset before turning off ADC internal regulator */
|
||||
while(LL_ADC_IsEnabled(p_ADCHandle) == 1UL);
|
||||
|
||||
/* Wait until ADC_CR_ADSTP bit is reset before turning off ADC internal regulator */
|
||||
while(LL_ADC_REG_IsStopConversionOngoing(p_ADCHandle) == 1U);
|
||||
|
||||
/* Disable ADC internal voltage regulator */
|
||||
LL_ADC_DisableInternalRegulator(p_ADCHandle);
|
||||
while(LL_ADC_IsInternalRegulatorEnabled(p_ADCHandle) == 1U);
|
||||
|
||||
/* Peripharal clock disable */
|
||||
ADCCTRL_DISABLE_CLOCK ();
|
||||
}
|
||||
|
||||
UTILS_EXIT_CRITICAL_SECTION();
|
||||
|
||||
SYSTEM_DEBUG_SIGNAL_RESET(ADC_DEACTIVATION);
|
||||
}
|
||||
|
||||
ADCCTRL_Cmd_Status_t AdcConfigure (const ADCCTRL_Handle_t * const p_Handle)
|
||||
{
|
||||
ADCCTRL_Cmd_Status_t error = ADCCTRL_OK;
|
||||
|
||||
__IO uint32_t backup_setting_adc_dma_transfer = 0U;
|
||||
|
||||
LL_ADC_InitTypeDef ADC_InitStruct = {0};
|
||||
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
|
||||
|
||||
/* DeInit the ADC module */
|
||||
if (SUCCESS != LL_ADC_DeInit (p_ADCHandle))
|
||||
{
|
||||
error = ADCCTRL_NOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Restart a calibration */
|
||||
/* Disable ADC DMA transfer request during calibration */
|
||||
/* Note: Specificity of this STM32 series: Calibration factor is */
|
||||
/* available in data register and also transferred by DMA. */
|
||||
/* To not insert ADC calibration factor among ADC conversion data */
|
||||
/* in DMA destination address, DMA transfer must be disabled during */
|
||||
/* calibration. */
|
||||
backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(p_ADCHandle);
|
||||
LL_ADC_REG_SetDMATransfer(p_ADCHandle, LL_ADC_REG_DMA_TRANSFER_NONE);
|
||||
|
||||
/* Run ADC self calibration */
|
||||
LL_ADC_StartCalibration(p_ADCHandle);
|
||||
|
||||
/* Poll for ADC effectively calibrated */
|
||||
while (LL_ADC_IsCalibrationOnGoing(p_ADCHandle) != 0);
|
||||
|
||||
/* Restore ADC DMA transfer request after calibration */
|
||||
LL_ADC_REG_SetDMATransfer(p_ADCHandle, backup_setting_adc_dma_transfer);
|
||||
|
||||
/* Delay required between ADC end of calibration and ADC enable */
|
||||
/* LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES --> 2 cycles */
|
||||
__asm("mov r0, r0");
|
||||
__asm("mov r0, r0");
|
||||
}
|
||||
|
||||
/* All OK ? */
|
||||
if (ADCCTRL_OK == error)
|
||||
{
|
||||
/* Update init and configuration parameters with requested values */
|
||||
ADC_InitStruct.Resolution = p_Handle->InitConf.ConvParams.Resolution;
|
||||
ADC_InitStruct.DataAlignment = p_Handle->InitConf.ConvParams.DataAlign;
|
||||
|
||||
ADC_REG_InitStruct.TriggerSource = p_Handle->InitConf.ConvParams.TriggerStart;
|
||||
ADC_REG_InitStruct.SequencerLength = p_Handle->InitConf.SeqParams.Length;
|
||||
ADC_REG_InitStruct.SequencerDiscont = p_Handle->InitConf.SeqParams.DiscMode;
|
||||
ADC_REG_InitStruct.ContinuousMode = p_Handle->InitConf.ConvParams.ConversionMode;
|
||||
ADC_REG_InitStruct.DMATransfer = p_Handle->InitConf.ConvParams.DmaTransfer;
|
||||
ADC_REG_InitStruct.Overrun = p_Handle->InitConf.ConvParams.Overrun;
|
||||
|
||||
/* Configure Regular Channel - Only for internal channels */
|
||||
if (LL_ADC_CHANNEL_VREFINT == p_Handle->ChannelConf.Channel)
|
||||
{
|
||||
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p_ADCHandle),
|
||||
LL_ADC_PATH_INTERNAL_VREFINT);
|
||||
}
|
||||
else if (LL_ADC_CHANNEL_TEMPSENSOR == p_Handle->ChannelConf.Channel)
|
||||
{
|
||||
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p_ADCHandle),
|
||||
LL_ADC_PATH_INTERNAL_TEMPSENSOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p_ADCHandle),
|
||||
LL_ADC_PATH_INTERNAL_NONE);
|
||||
}
|
||||
|
||||
/* Set trigger frequency */
|
||||
LL_ADC_SetTriggerFrequencyMode(p_ADCHandle,
|
||||
p_Handle->InitConf.ConvParams.TriggerFrequencyMode);
|
||||
|
||||
/* Apply the requested ADC configuration - Init part */
|
||||
if (SUCCESS != LL_ADC_Init(p_ADCHandle,
|
||||
&ADC_InitStruct))
|
||||
{
|
||||
error = ADCCTRL_NOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Sequencer if configurable */
|
||||
LL_ADC_REG_SetSequencerConfigurable(p_ADCHandle,
|
||||
p_Handle->InitConf.SeqParams.Setup);
|
||||
|
||||
/* Apply the requested ADC configuration - Register init part */
|
||||
if (SUCCESS != LL_ADC_REG_Init(p_ADCHandle,
|
||||
&ADC_REG_InitStruct))
|
||||
{
|
||||
error = ADCCTRL_NOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Low power characteristics */
|
||||
LL_ADC_SetLPModeAutoPowerOff(p_ADCHandle,
|
||||
p_Handle->InitConf.LowPowerParams.AutoPowerOff);
|
||||
LL_ADC_SetLPModeAutonomousDPD(p_ADCHandle,
|
||||
p_Handle->InitConf.LowPowerParams.AutonomousDPD);
|
||||
|
||||
/* Set Sampling time for channels */
|
||||
LL_ADC_SetSamplingTimeCommonChannels(p_ADCHandle,
|
||||
LL_ADC_SAMPLINGTIME_COMMON_1,
|
||||
p_Handle->InitConf.ConvParams.SamplingTimeCommon1);
|
||||
LL_ADC_SetSamplingTimeCommonChannels(p_ADCHandle,
|
||||
LL_ADC_SAMPLINGTIME_COMMON_2,
|
||||
p_Handle->InitConf.ConvParams.SamplingTimeCommon2);
|
||||
|
||||
/* Configure the channel */
|
||||
LL_ADC_REG_SetSequencerRanks(p_ADCHandle,
|
||||
p_Handle->ChannelConf.Rank,
|
||||
p_Handle->ChannelConf.Channel);
|
||||
LL_ADC_SetChannelSamplingTime(p_ADCHandle,
|
||||
p_Handle->ChannelConf.Channel,
|
||||
p_Handle->ChannelConf.SamplingTime);
|
||||
|
||||
/* Update the current configuration */
|
||||
CurrentConfig = p_Handle->Uid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t AdcReadRaw (const ADCCTRL_Handle_t * const p_Handle)
|
||||
{
|
||||
/* Variables for ADC conversion data */
|
||||
__IO uint16_t uhADCxConvertedData = 0x00;
|
||||
|
||||
/* Perform ADC group regular conversion start, poll for conversion */
|
||||
/* completion. */
|
||||
ConversionStartPoll_ADC_GrpRegular ();
|
||||
|
||||
/* Retrieve ADC conversion data */
|
||||
switch (p_Handle->InitConf.ConvParams.Resolution)
|
||||
{
|
||||
case LL_ADC_RESOLUTION_12B:
|
||||
{
|
||||
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_12B;
|
||||
|
||||
uhADCxConvertedData = LL_ADC_REG_ReadConversionData12(p_ADCHandle);
|
||||
|
||||
break;
|
||||
}
|
||||
case LL_ADC_RESOLUTION_10B:
|
||||
{
|
||||
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_10B;
|
||||
|
||||
uhADCxConvertedData = LL_ADC_REG_ReadConversionData10(p_ADCHandle);
|
||||
|
||||
break;
|
||||
}
|
||||
case LL_ADC_RESOLUTION_8B:
|
||||
{
|
||||
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_8B;
|
||||
|
||||
uhADCxConvertedData = LL_ADC_REG_ReadConversionData8(p_ADCHandle);
|
||||
|
||||
break;
|
||||
}
|
||||
case LL_ADC_RESOLUTION_6B:
|
||||
{
|
||||
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_6B;
|
||||
|
||||
uhADCxConvertedData = LL_ADC_REG_ReadConversionData6(p_ADCHandle);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* Do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return uhADCxConvertedData;
|
||||
}
|
||||
|
||||
void ConversionStartPoll_ADC_GrpRegular (void)
|
||||
{
|
||||
|
||||
/* Start ADC group regular conversion */
|
||||
/* Note: Hardware constraint (refer to description of the function */
|
||||
/* below): */
|
||||
/* On this STM32 series, setting of this feature is conditioned to */
|
||||
/* ADC state: */
|
||||
/* ADC must be enabled without conversion on going on group regular, */
|
||||
/* without ADC disable command on going. */
|
||||
/* Note: In this example, all these checks are not necessary but are */
|
||||
/* implemented anyway to show the best practice usages */
|
||||
/* corresponding to reference manual procedure. */
|
||||
/* Software can be optimized by removing some of these checks, if */
|
||||
/* they are not relevant considering previous settings and actions */
|
||||
/* in user application. */
|
||||
if ((LL_ADC_IsEnabled(p_ADCHandle) == 1) &&
|
||||
(LL_ADC_IsDisableOngoing(p_ADCHandle) == 0) &&
|
||||
(LL_ADC_REG_IsConversionOngoing(p_ADCHandle) == 0) )
|
||||
{
|
||||
LL_ADC_REG_StartConversion(p_ADCHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error: ADC conversion start could not be performed */
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
while (LL_ADC_IsActiveFlag_EOC(p_ADCHandle) == 0);
|
||||
|
||||
/* Clear flag ADC group regular end of unitary conversion */
|
||||
/* Note: This action is not needed here, because flag ADC group regular */
|
||||
/* end of unitary conversion is cleared automatically when */
|
||||
/* software reads conversion data from ADC data register. */
|
||||
/* Nevertheless, this action is done anyway to show how to clear */
|
||||
/* this flag, needed if conversion data is not always read */
|
||||
/* or if group injected end of unitary conversion is used (for */
|
||||
/* devices with group injected available). */
|
||||
LL_ADC_ClearFlag_EOC(p_ADCHandle);
|
||||
}
|
||||
|
||||
/* Weak function Definition --------------------------------------------------*/
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_MutexTake (void)
|
||||
{
|
||||
return ADCCTRL_OK;
|
||||
}
|
||||
|
||||
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_MutexRelease (void)
|
||||
{
|
||||
return ADCCTRL_OK;
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file adc_ctrl.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for ADC client manager module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ADC_CTRL_H
|
||||
#define ADC_CTRL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Utilities */
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC command status codes
|
||||
*/
|
||||
typedef enum ADCCTRL_Cmd_Status
|
||||
{
|
||||
ADCCTRL_OK,
|
||||
ADCCTRL_NOK,
|
||||
ADCCTRL_BUSY,
|
||||
ADCCTRL_HANDLE_ALREADY_REGISTERED,
|
||||
ADCCTRL_HANDLE_NOT_REGISTERED,
|
||||
ADCCTRL_HANDLE_NOT_VALID,
|
||||
ADCCTRL_ERROR_NULL_POINTER,
|
||||
ADCCTRL_ERROR_CONFIG,
|
||||
ADCCTRL_ERROR_STATE,
|
||||
ADCCTRL_UNKNOWN,
|
||||
} ADCCTRL_Cmd_Status_t;
|
||||
|
||||
/**
|
||||
* @brief ADC IP state
|
||||
*/
|
||||
typedef enum ADCCTRL_Ip_State
|
||||
{
|
||||
ADC_OFF,
|
||||
ADC_ON
|
||||
} ADCCTRL_Ip_State_t;
|
||||
|
||||
/**
|
||||
* @brief ADC handle states
|
||||
*/
|
||||
typedef enum ADCCTRL_HandleState
|
||||
{
|
||||
ADCCTRL_HANDLE_NOT_REG,
|
||||
ADCCTRL_HANDLE_REG,
|
||||
} ADCCTRL_HandleState_t;
|
||||
|
||||
/**
|
||||
* @brief ADC Init configuration structure - Conversion parameters
|
||||
*/
|
||||
typedef struct ADCCTRL_ConvParameters
|
||||
{
|
||||
uint32_t TriggerFrequencyMode; /*!< Set ADC Trigger frequency mode.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_FREQ */
|
||||
|
||||
uint32_t Resolution; /*!< Configure the ADC resolution.
|
||||
This parameter can be a value of @ref ADC_LL_EC_RESOLUTION */
|
||||
|
||||
uint32_t DataAlign; /*!< Specify ADC data alignment in conversion data register (right or left).
|
||||
This parameter can be a value of @ref ADC_LL_EC_DATA_ALIGN */
|
||||
|
||||
uint32_t TriggerStart; /*!< Select the source used to trigger ADC conversion
|
||||
start.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_SOURCE.*/
|
||||
|
||||
uint32_t TriggerEdge; /*!< Select the Edge used for trigger.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_EDGE.*/
|
||||
|
||||
uint32_t ConversionMode; /*!< Configure the conversion mode of ADC.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_CONTINUOUS_MODE */
|
||||
|
||||
uint32_t DmaTransfer; /*!< DMA transfer of ADC conversion data.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_DMA_TRANSFER */
|
||||
|
||||
uint32_t Overrun; /*!< Select the behavior in case of overrun: data overwritten or preserved (default).
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_OVR_DATA_BEHAVIOR. */
|
||||
|
||||
uint32_t SamplingTimeCommon1; /*!< Set sampling time common to a group of channels.
|
||||
This parameter can be a value of @ref ADC_LL_EC_CHANNEL_SAMPLINGTIME */
|
||||
|
||||
uint32_t SamplingTimeCommon2; /*!< Set sampling time common to a group of channels, second common setting possible.
|
||||
This parameter can be a value of @ref ADC_LL_EC_CHANNEL_SAMPLINGTIME */
|
||||
}ADCCTRL_ConvParameters_t;
|
||||
|
||||
/**
|
||||
* @brief ADC Init configuration structure - Sequencer parameters
|
||||
*/
|
||||
typedef struct ADCCTRL_SeqParameters
|
||||
{
|
||||
uint32_t Setup; /*!< Set ADC sequencer configuration flexibility.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_MODE */
|
||||
|
||||
uint32_t Length; /*!< Set ADC sequencer scan length.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_SCAN_LENGTH */
|
||||
|
||||
uint32_t DiscMode; /*!< Set ADC sequencer discontinuous mode.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_DISCONT_MODE */
|
||||
}ADCCTRL_SeqParameters_t;
|
||||
|
||||
/**
|
||||
* @brief ADC Init configuration structure - Low power parameters
|
||||
*/
|
||||
typedef struct ADCCTRL_LowPowerParameters
|
||||
{
|
||||
FunctionalState AutoPowerOff; /*!< Enable or Disable ADC Auto Power OFF mode.
|
||||
This parameter can be set to ENABLE or DISABLE */
|
||||
|
||||
uint32_t AutonomousDPD; /*!< Enable or Disable ADC Autonomous Deep Power Down Mode.
|
||||
This parameter can be a value of @ref ADC_LL_EC_AUTONOMOUS_DEEP_POWER_DOWN_MODE */
|
||||
}ADCCTRL_LowPowerParameters_t;
|
||||
|
||||
/**
|
||||
* @brief ADC Init configuration structure
|
||||
*/
|
||||
typedef struct ADCCTRL_InitConfig
|
||||
{
|
||||
ADCCTRL_ConvParameters_t ConvParams;
|
||||
ADCCTRL_SeqParameters_t SeqParams;
|
||||
ADCCTRL_LowPowerParameters_t LowPowerParams;
|
||||
} ADCCTRL_InitConfig_t;
|
||||
|
||||
/**
|
||||
* @brief ADC Channel configuration structure
|
||||
*/
|
||||
typedef struct ADCCTRL_ChannelConfig
|
||||
{
|
||||
uint32_t Channel; /*!< Specify the channel to configure into ADC regular group.
|
||||
This parameter can be a value of @ref ADC_LL_EC_CHANNEL */
|
||||
|
||||
uint32_t Rank; /*!< Add or remove the channel from ADC regular group sequencer and specify its
|
||||
conversion rank.
|
||||
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_RANKS */
|
||||
|
||||
uint32_t SamplingTime; /*!< Sampling time value to be set for the selected channel.
|
||||
This parameter can be a value of @ref ADC_LL_EC_SAMPLINGTIME_COMMON */
|
||||
} ADCCTRL_ChannelConfig_t;
|
||||
|
||||
/**
|
||||
* @brief ADC handle typedef
|
||||
*/
|
||||
typedef struct ADCCTRL_Handle
|
||||
{
|
||||
uint32_t Uid; /* Id of the Handle instance */
|
||||
ADCCTRL_HandleState_t State; /* State of the ADC Controller handle */
|
||||
ADCCTRL_InitConfig_t InitConf; /* Init configuration of the ADC */
|
||||
ADCCTRL_ChannelConfig_t ChannelConf; /* Channel configuration of the ADC */
|
||||
} ADCCTRL_Handle_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the adc controller
|
||||
*
|
||||
* @retval State of the initialization
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_Init(void);
|
||||
|
||||
/**
|
||||
* @brief Register a ADC handle
|
||||
*
|
||||
* @param p_Handle: Handle to register
|
||||
*
|
||||
* @return State of the handle initialization
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_RegisterHandle (ADCCTRL_Handle_t * const p_Handle);
|
||||
|
||||
/**
|
||||
* @brief Request a specific state for the ADC IP - Either On or Off
|
||||
*
|
||||
* @param p_Handle: ADC handle
|
||||
* @param State: Requested state to apply
|
||||
*
|
||||
* @return State of the operation
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_RequestIpState (const ADCCTRL_Handle_t * const p_Handle,
|
||||
const ADCCTRL_Ip_State_t State);
|
||||
|
||||
/**
|
||||
* @brief Read raw value of the ADC
|
||||
*
|
||||
* @param p_Handle: ADC handle
|
||||
* @param p_ReadValue: Raw ADC value
|
||||
*
|
||||
* @retval Operation state
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_RequestRawValue (const ADCCTRL_Handle_t * const p_Handle,
|
||||
uint16_t * const p_ReadValue);
|
||||
|
||||
/**
|
||||
* @brief Read temperature from ADC temperature sensor
|
||||
*
|
||||
* @details The returned value is actual temperature sensor value
|
||||
*
|
||||
* @param p_Handle: ADC handle
|
||||
* @param p_ReadValue: Temperature measurement
|
||||
*
|
||||
* @retval Operation state
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_RequestTemperature (const ADCCTRL_Handle_t * const p_Handle,
|
||||
int16_t * const p_ReadValue);
|
||||
|
||||
/**
|
||||
* @brief Read Voltage from ADC
|
||||
*
|
||||
* @details The returned value is actual Voltage value in mVolts
|
||||
*
|
||||
* @param p_Handle: ADC handle
|
||||
* @param p_ReadValue: Core Voltage measurement
|
||||
*
|
||||
* @retval Operation state
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_RequestCoreVoltage (const ADCCTRL_Handle_t * const p_Handle,
|
||||
uint16_t * const p_ReadValue);
|
||||
|
||||
/**
|
||||
* @brief Read reference Voltage from ADC
|
||||
*
|
||||
* @details The returned value is actual reference Voltage value in mVolts
|
||||
*
|
||||
* @param p_Handle: ADC handle
|
||||
* @param p_ReadValue: Reference Voltage measurement
|
||||
*
|
||||
* @retval Operation state
|
||||
*/
|
||||
ADCCTRL_Cmd_Status_t ADCCTRL_RequestRefVoltage (const ADCCTRL_Handle_t * const p_Handle,
|
||||
uint16_t * const p_ReadValue);
|
||||
|
||||
/* Exported functions to be implemented by the user ------------------------- */
|
||||
/**
|
||||
* @brief Take ownership on the ADC mutex
|
||||
*
|
||||
* @details This function shall be implemented by the user
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_OK
|
||||
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_NOK
|
||||
*/
|
||||
extern ADCCTRL_Cmd_Status_t ADCCTRL_MutexTake (void);
|
||||
|
||||
/**
|
||||
* @brief Release ownership on the ADC mutex
|
||||
*
|
||||
* @details This function shall be implemented by the user
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_OK
|
||||
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_NOK
|
||||
*/
|
||||
extern ADCCTRL_Cmd_Status_t ADCCTRL_MutexRelease (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ADC_CTRL_H */
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_sys.c
|
||||
* @author MCD Application Team
|
||||
* @brief Application system for STM32WPAN Middleware.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "app_sys.h"
|
||||
#include "app_conf.h"
|
||||
#include "timer_if.h"
|
||||
#include "stm32_lpm.h"
|
||||
#include "ll_intf.h"
|
||||
#include "ll_sys.h"
|
||||
#if (UTIL_LPM_LEGACY_ENABLED == 0)
|
||||
#include "stm32_lpm_if.h"
|
||||
#endif
|
||||
|
||||
#if MAC
|
||||
#include "ral.h"
|
||||
#endif
|
||||
|
||||
/* External functions --------------------------------------------------------*/
|
||||
extern uint32_t llhwc_cmn_is_dp_slp_enabled(void);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/* Private variables --------------------------------------------------------*/
|
||||
static uint32_t wakeup_offset = RADIO_DEEPSLEEP_WAKEUP_TIME_US;
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#if SUPPORT_BLE
|
||||
void APP_SYS_BLE_EnterDeepSleep(void)
|
||||
{
|
||||
ble_stat_t cmd_status;
|
||||
uint32_t radio_remaining_time = 0;
|
||||
|
||||
if (ll_sys_dp_slp_get_state() == LL_SYS_DP_SLP_DISABLED)
|
||||
{
|
||||
/* Enable radio to retrieve next radio activity */
|
||||
|
||||
/* Getting next radio event time if any */
|
||||
cmd_status = ll_intf_le_get_remaining_time_for_next_event(&radio_remaining_time);
|
||||
UNUSED(cmd_status);
|
||||
assert_param(cmd_status == SUCCESS);
|
||||
|
||||
if (radio_remaining_time == LL_DP_SLP_NO_WAKEUP)
|
||||
{
|
||||
/* No next radio event scheduled */
|
||||
(void)ll_sys_dp_slp_enter(LL_DP_SLP_NO_WAKEUP);
|
||||
}
|
||||
else if (radio_remaining_time > wakeup_offset)
|
||||
{
|
||||
/* No event in a "near" futur */
|
||||
(void)ll_sys_dp_slp_enter(radio_remaining_time - wakeup_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (UTIL_LPM_LEGACY_ENABLED == 1)
|
||||
UTIL_LPM_SetOffMode(1U << CFG_LPM_LL_DEEPSLEEP, UTIL_LPM_DISABLE);
|
||||
#else /* (UTIL_LPM_LEGACY_ENABLED == 1) */
|
||||
#if (CFG_LPM_STOP1_SUPPORTED == 1)
|
||||
UTIL_LPM_SetMaxMode(1U << CFG_LPM_LL_DEEPSLEEP, UTIL_LPM_STOP1_MODE);
|
||||
#else /* (CFG_LPM_STOP1_SUPPORTED == 1) */
|
||||
UTIL_LPM_SetMaxMode(1U << CFG_LPM_LL_DEEPSLEEP, UTIL_LPM_SLEEP_MODE);
|
||||
#endif /* (CFG_LPM_STOP1_SUPPORTED == 1) */
|
||||
#endif /* (UTIL_LPM_LEGACY_ENABLED == 1) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /* SUPPORT_BLE */
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void APP_SYS_LPM_EnterLowPowerMode(void)
|
||||
{
|
||||
ral_instance_t radio_instance;
|
||||
uint8_t channel;
|
||||
uint64_t next_radio_evt;
|
||||
|
||||
/* Ensure there are no radio events (implement bsp function like bsp_is_radio_idle() ) */
|
||||
ral_event_state_enum_t radio_state = ral_get_current_event_state( &radio_instance, &channel );
|
||||
LL_UNUSED(radio_instance);
|
||||
LL_UNUSED(channel);
|
||||
if (radio_state != RAL_IDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
next_radio_evt = os_timer_get_earliest_time();
|
||||
if ( llhwc_cmn_is_dp_slp_enabled() == 0 )
|
||||
{
|
||||
if ( next_radio_evt > wakeup_offset )
|
||||
{
|
||||
/* No event in a "near" futur */
|
||||
ll_sys_dp_slp_enter( next_radio_evt - wakeup_offset );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SUPPORT_BLE */
|
||||
|
||||
void APP_SYS_SetWakeupOffset(uint32_t wakeup_offset_us)
|
||||
{
|
||||
wakeup_offset = wakeup_offset_us;
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file crc_ctrl.c
|
||||
* @author MCD Application Team
|
||||
* @brief Source for CRC client controller module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* Utilities */
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Own header files */
|
||||
#include "crc_ctrl.h"
|
||||
#include "crc_ctrl_conf.h"
|
||||
|
||||
/* HAL CRC header */
|
||||
#include "stm32wbaxx_hal_crc.h"
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initial value define for configuration tracking number
|
||||
*
|
||||
*/
|
||||
#define CRCCTRL_NO_CONFIG (uint32_t)(0x00000000u)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Tracker of the current applied configuration
|
||||
*/
|
||||
static uint32_t CurrentConfig = CRCCTRL_NO_CONFIG;
|
||||
|
||||
/**
|
||||
* @brief Higher registered handle ID
|
||||
*/
|
||||
static uint32_t MaxRegisteredId = CRCCTRL_NO_CONFIG;
|
||||
|
||||
/**
|
||||
* @brief Handle of the HAL CRC
|
||||
*/
|
||||
static CRC_HandleTypeDef CRCHandle =
|
||||
{
|
||||
.Instance = CRCCTRL_HWADDR,
|
||||
};
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/**
|
||||
* @brief Configure CRC IP
|
||||
* @param p_Handle: CRC handle
|
||||
* @retval State of the configuration
|
||||
*/
|
||||
static inline HAL_StatusTypeDef CrcConfigure (CRCCTRL_Handle_t * const p_Handle);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_Init (void)
|
||||
{
|
||||
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
|
||||
|
||||
/* Try to take the CRC mutex */
|
||||
error = CRCCTRL_MutexTake ();
|
||||
|
||||
if (CRCCTRL_OK == error)
|
||||
{
|
||||
CurrentConfig = CRCCTRL_NO_CONFIG;
|
||||
|
||||
CRCHandle.State = HAL_CRC_STATE_RESET;
|
||||
|
||||
CRCHandle.Instance = CRCCTRL_HWADDR;
|
||||
|
||||
/* Release the mutex */
|
||||
CRCCTRL_MutexRelease ();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_RegisterHandle (CRCCTRL_Handle_t * const p_Handle)
|
||||
{
|
||||
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
|
||||
|
||||
if (NULL == p_Handle)
|
||||
{
|
||||
error = CRCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
else if (HANDLE_REG == p_Handle->State)
|
||||
{
|
||||
error = CRCCTRL_HANDLE_ALREADY_REGISTERED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the CRC mutex */
|
||||
error = CRCCTRL_MutexTake ();
|
||||
|
||||
if (CRCCTRL_OK == error)
|
||||
{
|
||||
/* Update the maximum registered handle */
|
||||
MaxRegisteredId = MaxRegisteredId + 1u;
|
||||
/* Update the handle UUID */
|
||||
p_Handle->Uid = MaxRegisteredId;
|
||||
/* Init the previous value */
|
||||
p_Handle->PreviousComputedValue = p_Handle->Configuration.InitValue;
|
||||
/* Set handle as initialized */
|
||||
p_Handle->State = HANDLE_REG;
|
||||
|
||||
/* Release the mutex */
|
||||
CRCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_Calculate (CRCCTRL_Handle_t * const p_Handle,
|
||||
uint32_t a_Payload[],
|
||||
const uint32_t PayloadSize,
|
||||
uint32_t * const p_ConmputedValue)
|
||||
{
|
||||
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
|
||||
HAL_StatusTypeDef eReturn = HAL_OK;
|
||||
|
||||
/* Null pointer for handle or payload */
|
||||
if ((NULL == p_Handle) || (NULL == a_Payload) || (NULL == p_ConmputedValue))
|
||||
{
|
||||
error = CRCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
/* Handle not init */
|
||||
else if (HANDLE_NOT_REG == p_Handle->State)
|
||||
{
|
||||
error = CRCCTRL_HANDLE_NOT_REGISTERED;
|
||||
}
|
||||
/* Handle not in the range */
|
||||
else if ((MaxRegisteredId < p_Handle->Uid) ||
|
||||
(CRCCTRL_NO_CONFIG >= p_Handle->Uid))
|
||||
{
|
||||
error = CRCCTRL_HANDLE_NOT_VALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the CRC mutex */
|
||||
error = CRCCTRL_MutexTake ();
|
||||
|
||||
if (CRCCTRL_OK == error)
|
||||
{
|
||||
/* Is the current config IS NOT the same as the one requested ? */
|
||||
if (CurrentConfig != p_Handle->Uid)
|
||||
{
|
||||
/* Configure the CRC before use */
|
||||
eReturn = CrcConfigure (p_Handle);
|
||||
}
|
||||
|
||||
if (eReturn == HAL_OK)
|
||||
{
|
||||
*p_ConmputedValue = HAL_CRC_Calculate (&CRCHandle, a_Payload, PayloadSize);
|
||||
|
||||
/* Update the handle with the computed value */
|
||||
p_Handle->PreviousComputedValue = *p_ConmputedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = CRCCTRL_ERROR_CONFIG;
|
||||
}
|
||||
|
||||
/* Release the mutex */
|
||||
CRCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_Accumulate (CRCCTRL_Handle_t * const p_Handle,
|
||||
uint32_t a_Payload[],
|
||||
const uint32_t PayloadSize,
|
||||
uint32_t * const p_ConmputedValue)
|
||||
{
|
||||
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
|
||||
|
||||
/* Null pointer for handle or payload */
|
||||
if ((NULL == p_Handle) || (NULL == a_Payload) || (NULL == p_ConmputedValue))
|
||||
{
|
||||
error = CRCCTRL_ERROR_NULL_POINTER;
|
||||
}
|
||||
/* Handle not init */
|
||||
else if (HANDLE_NOT_REG == p_Handle->State)
|
||||
{
|
||||
error = CRCCTRL_HANDLE_NOT_REGISTERED;
|
||||
}
|
||||
/* Handle not in the range */
|
||||
else if ((MaxRegisteredId < p_Handle->Uid) ||
|
||||
(CRCCTRL_NO_CONFIG >= p_Handle->Uid))
|
||||
{
|
||||
error = CRCCTRL_HANDLE_NOT_VALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to take the CRC mutex */
|
||||
error = CRCCTRL_MutexTake ();
|
||||
|
||||
if (CRCCTRL_OK == error)
|
||||
{
|
||||
/* Check if the config has to change */
|
||||
if (CurrentConfig == p_Handle->Uid)
|
||||
{
|
||||
*p_ConmputedValue = HAL_CRC_Accumulate (&CRCHandle,
|
||||
a_Payload,
|
||||
PayloadSize);
|
||||
|
||||
/* Update the handle with the computed value */
|
||||
p_Handle->PreviousComputedValue = *p_ConmputedValue;
|
||||
}
|
||||
/* Configure the CRC before use */
|
||||
else if (HAL_OK == CrcConfigure (p_Handle))
|
||||
{
|
||||
/* Before starting the accumulation, the init register shall be written with the previous value */
|
||||
CRCHandle.Instance->INIT = p_Handle->PreviousComputedValue;
|
||||
|
||||
*p_ConmputedValue = HAL_CRC_Calculate (&CRCHandle,
|
||||
a_Payload,
|
||||
PayloadSize);
|
||||
|
||||
/* Update the handle with the computed value */
|
||||
p_Handle->PreviousComputedValue = *p_ConmputedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = CRCCTRL_ERROR_CONFIG;
|
||||
}
|
||||
|
||||
/* Release the mutex */
|
||||
CRCCTRL_MutexRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Private function Definition -----------------------------------------------*/
|
||||
HAL_StatusTypeDef CrcConfigure (CRCCTRL_Handle_t * const p_Handle)
|
||||
{
|
||||
HAL_StatusTypeDef error = HAL_OK;
|
||||
|
||||
/* No need to DeInit if the CRC if it is not yet initialized */
|
||||
if (HAL_CRC_STATE_RESET != CRCHandle.State)
|
||||
{
|
||||
/* DeInit the CRC module */
|
||||
error = HAL_CRC_DeInit(&CRCHandle);
|
||||
}
|
||||
|
||||
/* All OK ? */
|
||||
if (HAL_OK == error)
|
||||
{
|
||||
/* Fulfill the configuration part */
|
||||
CRCHandle.Init.CRCLength = p_Handle->Configuration.CRCLength;
|
||||
CRCHandle.Init.DefaultInitValueUse = p_Handle->Configuration.DefaultInitValueUse;
|
||||
CRCHandle.Init.DefaultPolynomialUse = p_Handle->Configuration.DefaultPolynomialUse;
|
||||
CRCHandle.Init.GeneratingPolynomial = p_Handle->Configuration.GeneratingPolynomial;
|
||||
CRCHandle.Init.InitValue = p_Handle->Configuration.InitValue;
|
||||
CRCHandle.Init.InputDataInversionMode = p_Handle->Configuration.InputDataInversionMode;
|
||||
CRCHandle.Init.OutputDataInversionMode = p_Handle->Configuration.OutputDataInversionMode;
|
||||
CRCHandle.InputDataFormat = p_Handle->Configuration.InputDataFormat;
|
||||
|
||||
/* Apply the requested CRC configuration */
|
||||
error = HAL_CRC_Init(&CRCHandle);
|
||||
|
||||
if (HAL_OK == error)
|
||||
{
|
||||
/* Update the current configuration */
|
||||
CurrentConfig = p_Handle->Uid;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There must be an issue with configuration, clean the configuration */
|
||||
memset ((void *)(&CRCHandle.Init),
|
||||
0x00,
|
||||
sizeof (CRC_InitTypeDef));
|
||||
|
||||
CRCHandle.InputDataFormat = 0x00u;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Weak function Definition --------------------------------------------------*/
|
||||
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_MutexTake (void)
|
||||
{
|
||||
return CRCCTRL_OK;
|
||||
}
|
||||
|
||||
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_MutexRelease (void)
|
||||
{
|
||||
return CRCCTRL_OK;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file crc_ctrl.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for CRC client manager module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2023 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef CRC_CTRL_H
|
||||
#define CRC_CTRL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Utilities */
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* HAL CRC header */
|
||||
#include "stm32wbaxx_hal_crc.h"
|
||||
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief CRC command status codes
|
||||
*/
|
||||
typedef enum CRCCTRL_Cmd_Status
|
||||
{
|
||||
CRCCTRL_OK,
|
||||
CRCCTRL_NOK,
|
||||
CRCCTRL_BUSY,
|
||||
CRCCTRL_HANDLE_ALREADY_REGISTERED,
|
||||
CRCCTRL_HANDLE_NOT_REGISTERED,
|
||||
CRCCTRL_HANDLE_NOT_VALID,
|
||||
CRCCTRL_ERROR_NULL_POINTER,
|
||||
CRCCTRL_ERROR_CONFIG,
|
||||
CRCCTRL_UNKNOWN,
|
||||
} CRCCTRL_Cmd_Status_t;
|
||||
|
||||
/**
|
||||
* @brief CRC command status codes
|
||||
*/
|
||||
typedef enum CRCCTRL_HandleState
|
||||
{
|
||||
HANDLE_NOT_REG,
|
||||
HANDLE_REG,
|
||||
} CRCCTRL_HandleState_t;
|
||||
|
||||
/**
|
||||
* @brief CRC configuration structure
|
||||
*
|
||||
*/
|
||||
typedef struct CRCCTRL_Config
|
||||
{
|
||||
uint8_t DefaultPolynomialUse; /*!< This parameter is a value of @ref CRC_Default_Polynomial and indicates if default polynomial is used.
|
||||
If set to DEFAULT_POLYNOMIAL_ENABLE, resort to default
|
||||
X^32 + X^26 + X^23 + X^22 + X^16 + X^12 + X^11 + X^10 +X^8 + X^7 + X^5 +
|
||||
X^4 + X^2+ X +1.
|
||||
In that case, there is no need to set GeneratingPolynomial field.
|
||||
If otherwise set to DEFAULT_POLYNOMIAL_DISABLE, GeneratingPolynomial and
|
||||
CRCLength fields must be set. */
|
||||
|
||||
uint8_t DefaultInitValueUse; /*!< This parameter is a value of @ref CRC_Default_InitValue_Use and indicates if default init value is used.
|
||||
If set to DEFAULT_INIT_VALUE_ENABLE, resort to default
|
||||
0xFFFFFFFF value. In that case, there is no need to set InitValue field. If
|
||||
otherwise set to DEFAULT_INIT_VALUE_DISABLE, InitValue field must be set. */
|
||||
|
||||
uint32_t GeneratingPolynomial; /*!< Set CRC generating polynomial as a 7, 8, 16 or 32-bit long value for a polynomial degree
|
||||
respectively equal to 7, 8, 16 or 32. This field is written in normal,
|
||||
representation e.g., for a polynomial of degree 7, X^7 + X^6 + X^5 + X^2 + 1
|
||||
is written 0x65. No need to specify it if DefaultPolynomialUse is set to
|
||||
DEFAULT_POLYNOMIAL_ENABLE. */
|
||||
|
||||
uint32_t CRCLength; /*!< This parameter is a value of @ref CRC_Polynomial_Sizes and indicates CRC length.
|
||||
Value can be either one of
|
||||
@arg @ref CRC_POLYLENGTH_32B (32-bit CRC),
|
||||
@arg @ref CRC_POLYLENGTH_16B (16-bit CRC),
|
||||
@arg @ref CRC_POLYLENGTH_8B (8-bit CRC),
|
||||
@arg @ref CRC_POLYLENGTH_7B (7-bit CRC). */
|
||||
|
||||
uint32_t InitValue; /*!< Init value to initiate CRC computation. No need to specify it if DefaultInitValueUse
|
||||
is set to DEFAULT_INIT_VALUE_ENABLE. */
|
||||
|
||||
uint32_t InputDataInversionMode; /*!< This parameter is a value of @ref CRCEx_Input_Data_Inversion and specifies input data inversion mode.
|
||||
Can be either one of the following values
|
||||
@arg @ref CRC_INPUTDATA_INVERSION_NONE no input data inversion
|
||||
@arg @ref CRC_INPUTDATA_INVERSION_BYTE byte-wise inversion, 0x1A2B3C4D
|
||||
becomes 0x58D43CB2
|
||||
@arg @ref CRC_INPUTDATA_INVERSION_HALFWORD halfword-wise inversion,
|
||||
0x1A2B3C4D becomes 0xD458B23C
|
||||
@arg @ref CRC_INPUTDATA_INVERSION_WORD word-wise inversion, 0x1A2B3C4D
|
||||
becomes 0xB23CD458 */
|
||||
|
||||
uint32_t OutputDataInversionMode; /*!< This parameter is a value of @ref CRCEx_Output_Data_Inversion and specifies output data (i.e. CRC) inversion mode.
|
||||
Can be either
|
||||
@arg @ref CRC_OUTPUTDATA_INVERSION_DISABLE no CRC inversion,
|
||||
@arg @ref CRC_OUTPUTDATA_INVERSION_ENABLE CRC 0x11223344 is converted
|
||||
into 0x22CC4488 */
|
||||
|
||||
uint32_t InputDataFormat; /*!< This parameter is a value of @ref CRC_Input_Buffer_Format and specifies input data format.
|
||||
Can be either
|
||||
@arg @ref CRC_INPUTDATA_FORMAT_BYTES input data is a stream of bytes
|
||||
(8-bit data)
|
||||
@arg @ref CRC_INPUTDATA_FORMAT_HALFWORDS input data is a stream of
|
||||
half-words (16-bit data)
|
||||
@arg @ref CRC_INPUTDATA_FORMAT_WORDS input data is a stream of words
|
||||
(32-bit data)
|
||||
|
||||
Note that constant CRC_INPUT_FORMAT_UNDEFINED is defined but an initialization
|
||||
error must occur if InputBufferFormat is not one of the three values listed
|
||||
above */
|
||||
} CRCCTRL_Config_t;
|
||||
|
||||
typedef struct CRCCTRL_Handle
|
||||
{
|
||||
uint32_t Uid; /* Id of the Handle instance */
|
||||
uint32_t PreviousComputedValue; /* Previous CRC computed value for Accumulate purposes */
|
||||
CRCCTRL_HandleState_t State; /* State of the CRC Controller handle */
|
||||
CRCCTRL_Config_t Configuration; /* Configuration of the CRC */
|
||||
} CRCCTRL_Handle_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
/**
|
||||
* @brief Init the CRC Ctrl variables
|
||||
*
|
||||
* @return State of the handle initialization
|
||||
*/
|
||||
CRCCTRL_Cmd_Status_t CRCCTRL_Init (void);
|
||||
|
||||
/**
|
||||
* @brief Register a CRC handle
|
||||
*
|
||||
* @param p_Handle: Handle to register
|
||||
*
|
||||
* @return State of the handle registration
|
||||
*/
|
||||
CRCCTRL_Cmd_Status_t CRCCTRL_RegisterHandle (CRCCTRL_Handle_t * const p_Handle);
|
||||
|
||||
/**
|
||||
* @brief Compute the CRC of the given payload
|
||||
*
|
||||
* @param p_Handle: CRC handle
|
||||
* @param a_Payload: Address of the first payload element
|
||||
* @param PayloadSize: Size of the payload to compute the CRC
|
||||
* @param p_ComputedValue: Computed CRC (returned value LSBs for CRC shorter than 32 bits)
|
||||
*
|
||||
* @return State of the operation
|
||||
*/
|
||||
CRCCTRL_Cmd_Status_t CRCCTRL_Calculate (CRCCTRL_Handle_t * const p_Handle,
|
||||
uint32_t a_Payload[],
|
||||
const uint32_t PayloadSize,
|
||||
uint32_t * const p_ConmputedValue);
|
||||
|
||||
/**
|
||||
* @brief Keep computing the CRC of a given payload
|
||||
*
|
||||
* @details Computation starts with the previous computed CRC as initialization value.
|
||||
*
|
||||
* @details The CRCCTRL_Calculate shall be used before any call of this API.
|
||||
*
|
||||
* @param p_Handle: Address of the first payload element
|
||||
* @param a_Payload: Address of the first payload element
|
||||
* @param PayloadSize: Size of the payload to compute the CRC
|
||||
* @param p_ComputedValue: Computed CRC (returned value LSBs for CRC shorter than 32 bits)
|
||||
*
|
||||
* @return State of the operation
|
||||
*/
|
||||
CRCCTRL_Cmd_Status_t CRCCTRL_Accumulate (CRCCTRL_Handle_t * const p_Handle,
|
||||
uint32_t a_Payload[],
|
||||
const uint32_t PayloadSize,
|
||||
uint32_t * const p_ConmputedValue);
|
||||
|
||||
/* Exported functions to be implemented by the user ------------------------- */
|
||||
/**
|
||||
* @brief Take ownership on the CRC mutex
|
||||
*
|
||||
* @details This function shall be implemented by the user
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_OK
|
||||
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_NOK
|
||||
*/
|
||||
extern CRCCTRL_Cmd_Status_t CRCCTRL_MutexTake (void);
|
||||
|
||||
/**
|
||||
* @brief Release ownership on the CRC mutex
|
||||
*
|
||||
* @details This function shall be implemented by the user
|
||||
*
|
||||
* @return Status of the command
|
||||
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_OK
|
||||
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_NOK
|
||||
*/
|
||||
extern CRCCTRL_Cmd_Status_t CRCCTRL_MutexRelease (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CRC_CTRL_H */
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dbg_trace.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for dbg_trace.c
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef DBG_TRACE_H
|
||||
#define DBG_TRACE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
#if ( ( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ) )
|
||||
#define PRINT_LOG_BUFF_DBG(...) DbgTraceBuffer(__VA_ARGS__)
|
||||
#if ( CFG_DEBUG_TRACE_FULL != 0 )
|
||||
#define PRINT_MESG_DBG(...) do{printf("\r\n [%s][%s][%d] ", DbgTraceGetFileName(__FILE__),__FUNCTION__,__LINE__);printf(__VA_ARGS__);}while(0);
|
||||
#else
|
||||
#define PRINT_MESG_DBG printf
|
||||
#endif
|
||||
#else
|
||||
#define PRINT_LOG_BUFF_DBG(...)
|
||||
#define PRINT_MESG_DBG(...)
|
||||
#endif
|
||||
|
||||
#define PRINT_NO_MESG(...)
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Request the user to initialize the peripheral to output traces
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
extern void DbgOutputInit( void );
|
||||
|
||||
/**
|
||||
* @brief Request the user to sent the traces on the output peripheral
|
||||
*
|
||||
* @param p_data: Address of the buffer to be sent
|
||||
* @param size: Size of the data to be sent
|
||||
* @param cb: Function to be called when the data has been sent
|
||||
* @retval None
|
||||
*/
|
||||
extern void DbgOutputTraces( uint8_t *p_data, uint16_t size, void (*cb)(void) );
|
||||
|
||||
/**
|
||||
* @brief DbgTraceInit Initialize Logging feature.
|
||||
*
|
||||
* @param: None
|
||||
* @retval: None
|
||||
*/
|
||||
void DbgTraceInit( void );
|
||||
|
||||
/**********************************************************************************************************************/
|
||||
/** This function outputs into the log the buffer (in hex) and the provided format string and arguments.
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* @param pBuffer Buffer to be output into the logs.
|
||||
* @param u32Length Length of the buffer, in bytes.
|
||||
* @param strFormat The format string in printf() style.
|
||||
* @param ... Arguments of the format string.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
void DbgTraceBuffer( const void *pBuffer , uint32_t u32Length , const char *strFormat , ... );
|
||||
|
||||
const char *DbgTraceGetFileName( const char *fullpath );
|
||||
|
||||
/**
|
||||
* @brief Override the standard lib function to redirect printf to USART.
|
||||
* @param handle output handle (STDIO, STDERR...)
|
||||
* @param buf buffer to write
|
||||
* @param bufsize buffer size
|
||||
* @retval Number of elements written
|
||||
*/
|
||||
size_t DbgTraceWrite(int handle, const unsigned char * buf, size_t bufSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DBG_TRACE_H */
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file otp.c
|
||||
* @author MCD HW Board & MCD Application Team
|
||||
* @brief Source file for One Time Programmable (OTP) area
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "otp.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
HAL_StatusTypeDef OTP_Read(uint8_t index, OTP_Data_s** otp_ptr)
|
||||
{
|
||||
*otp_ptr = (OTP_Data_s*) (FLASH_OTP_BASE + FLASH_OTP_SIZE - 16);
|
||||
|
||||
while ( (*otp_ptr)->index != index && (*otp_ptr) != (OTP_Data_s*) FLASH_OTP_BASE)
|
||||
{
|
||||
(*otp_ptr) -= 1;
|
||||
}
|
||||
|
||||
if ((*otp_ptr)->index != index)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef OTP_Write(uint8_t* additional_data, uint8_t* bd_address, uint8_t hsetune, uint8_t index)
|
||||
{
|
||||
HAL_StatusTypeDef err = HAL_ERROR;
|
||||
OTP_Data_s otp_data;
|
||||
int i;
|
||||
|
||||
/* Fill OTP_Data_s structure */
|
||||
for (i = 0; i < sizeof(otp_data.additional_data); i++)
|
||||
{
|
||||
otp_data.additional_data[i] = additional_data[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(otp_data.bd_address); i++)
|
||||
{
|
||||
otp_data.bd_address[i] = bd_address[i];
|
||||
}
|
||||
|
||||
otp_data.hsetune = hsetune;
|
||||
otp_data.index = index;
|
||||
|
||||
/* Find free space */
|
||||
uint32_t free_address = FLASH_OTP_BASE;
|
||||
while ( ( *(uint64_t*)(free_address) != 0xFFFFFFFFFFFFFFFFUL ) &&
|
||||
( *(uint64_t*)(free_address + 8) != 0xFFFFFFFFFFFFFFFFUL ) &&
|
||||
( (free_address + 16) != FLASH_OTP_BASE + FLASH_OTP_SIZE ) )
|
||||
{
|
||||
free_address += 16;
|
||||
}
|
||||
|
||||
if ( ( *(uint64_t*)(free_address) == 0xFFFFFFFFFFFFFFFFUL ) &&
|
||||
( *(uint64_t*)(free_address + 8) == 0xFFFFFFFFFFFFFFFFUL ) )
|
||||
{
|
||||
/* Store OTP structure in OTP area */
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); /* Clear all Flash flags before write operation*/
|
||||
|
||||
err = HAL_FLASH_Unlock();
|
||||
err |= HAL_FLASH_Program(FLASH_NSCR1_PG, free_address, (uint32_t) &otp_data);
|
||||
err |= HAL_FLASH_Lock();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file otp.h
|
||||
* @author MCD HW Board & MCD Application Team
|
||||
* @brief Header file for One Time Programmable (OTP) area
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef OTP_H
|
||||
#define OTP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "stm32wbaxx_hal.h"
|
||||
#include "cmsis_compiler.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
|LSB MSB|
|
||||
--------------------------------------------------------------------------------
|
||||
| additional_data 8-bytes | bd_address 6 bytes | hsetune 1 byte | index 1 byte |
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
typedef __PACKED_STRUCT
|
||||
{
|
||||
uint8_t additional_data[8]; /*!< 64 bits of data to fill OTP slot Ex: MB184510 */
|
||||
uint8_t bd_address[6]; /*!< Bluetooth Device Address*/
|
||||
uint8_t hsetune; /*!< Load capacitance to be applied on HSE pad */
|
||||
uint8_t index; /*!< Structure index */
|
||||
} OTP_Data_s;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
#define DEFAULT_OTP_IDX 0
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported variables ------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* * @brief Minimal code to use the OTP_Read function:
|
||||
*
|
||||
OTP_Data_s* otp_ptr = NULL;
|
||||
|
||||
if (OTP_Read(DEFAULT_OTP_IDX, &otp_ptr) != HAL_OK) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
uint64_t bd_addr = (uint64_t) otp_ptr->bd_address[0] |
|
||||
(uint64_t) otp_ptr->bd_address[1] << 8 |
|
||||
(uint64_t) otp_ptr->bd_address[2] << 16 |
|
||||
(uint64_t) otp_ptr->bd_address[3] << 24 |
|
||||
(uint64_t) otp_ptr->bd_address[4] << 32 |
|
||||
(uint64_t) otp_ptr->bd_address[5] << 40 ;
|
||||
|
||||
uint8_t hsetune = otp_ptr->hsetune;
|
||||
uint8_t index = otp_ptr->index;
|
||||
*/
|
||||
HAL_StatusTypeDef OTP_Read(uint8_t index, OTP_Data_s** data);
|
||||
|
||||
/**
|
||||
* @brief Write OTP
|
||||
*/
|
||||
HAL_StatusTypeDef OTP_Write(uint8_t* additional_data, uint8_t* bd_address, uint8_t hsetune, uint8_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OTP_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,286 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file scm.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for scm.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef SCM_H
|
||||
#define SCM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
#if (CFG_SCM_SUPPORTED == 1)
|
||||
#include "stm32wbaxx_hal.h"
|
||||
#include "stm32wbaxx_ll_pwr.h"
|
||||
#include "stm32wbaxx_ll_rcc.h"
|
||||
#include "stm32wbaxx_ll_tim.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef enum {
|
||||
NO_CLOCK_CONFIG = 0,
|
||||
HSE_16MHZ,
|
||||
HSE_32MHZ,
|
||||
SYS_PLL,
|
||||
} scm_clockconfig_t;
|
||||
|
||||
typedef enum {
|
||||
LP,
|
||||
RUN,
|
||||
HSE16,
|
||||
HSE32,
|
||||
PLL,
|
||||
} scm_ws_lp_t;
|
||||
|
||||
typedef enum {
|
||||
HSEPRE_DISABLE = 0,
|
||||
HSEPRE_ENABLE
|
||||
} scm_hse_hsepre_t;
|
||||
|
||||
typedef enum {
|
||||
SCM_USER_APP,
|
||||
SCM_USER_LL_FW,
|
||||
SCM_USER_LL_HW_RCO_CLBR,
|
||||
TOTAL_CLIENT_NUM, /* To be at the end of the enum */
|
||||
} scm_user_id_t;
|
||||
|
||||
typedef enum {
|
||||
NO_PLL,
|
||||
PLL_INTEGER_MODE,
|
||||
PLL_FRACTIONAL_MODE,
|
||||
} scm_pll_mode_t;
|
||||
|
||||
typedef enum {
|
||||
SCM_RADIO_NOT_ACTIVE = 0,
|
||||
SCM_RADIO_ACTIVE,
|
||||
} scm_radio_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t are_pll_params_initialized;
|
||||
scm_pll_mode_t pll_mode;
|
||||
uint32_t PLLM;
|
||||
uint32_t PLLN;
|
||||
uint32_t PLLP;
|
||||
uint32_t PLLQ;
|
||||
uint32_t PLLR;
|
||||
uint32_t PLLFractional;
|
||||
uint32_t AHB5_PLL1_CLKDivider;
|
||||
} scm_pll_config_t;
|
||||
|
||||
typedef struct{
|
||||
scm_clockconfig_t targeted_clock_freq;
|
||||
uint32_t flash_ws_cfg;
|
||||
uint32_t sram_ws_cfg;
|
||||
scm_pll_config_t pll;
|
||||
} scm_system_clock_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief System Clock Manager init code
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void scm_init(void);
|
||||
|
||||
/**
|
||||
* @brief Setup the system clock source in usable configuration for Connectivity use cases.
|
||||
* Called at startup or out of low power modes.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void scm_setup(void);
|
||||
|
||||
/**
|
||||
* @brief Configure the PLL mode and parameters before PLL selection as system clock.
|
||||
* @param p_pll_config PLL coniguration to apply
|
||||
* @retval None
|
||||
* @note scm_pll_setconfig to be called before PLL activation (PLL set as system core clock)
|
||||
*/
|
||||
void scm_pll_setconfig(const scm_pll_config_t *p_pll_config);
|
||||
|
||||
/**
|
||||
* @brief Restore system clock configuration when moving out of standby.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void scm_standbyexit(void);
|
||||
|
||||
/**
|
||||
* @brief Return the state of the Radio.
|
||||
* @param None
|
||||
* @retval radio_state
|
||||
*/
|
||||
scm_radio_state_t isRadioActive(void);
|
||||
|
||||
/**
|
||||
* @brief Configure the PLL for switching fractional parameters on the fly.
|
||||
* @param pll_frac Up to date fractional configuration.
|
||||
* @retval None
|
||||
* @note A PLL update is requested only when the system clock is
|
||||
* running on the PLL with a different configuration that the
|
||||
* one required.
|
||||
*/
|
||||
void scm_pll_fractional_update(uint32_t pll_frac);
|
||||
|
||||
/**
|
||||
* @brief Set the HSE clock to the requested frequency.
|
||||
* @param user_id This parameter can be one of the following:
|
||||
* @arg SCM_USER_APP
|
||||
* @arg SCM_USER_LL_FW
|
||||
* @param sysclockconfig This parameter can be one of the following:
|
||||
* @arg HSE_16MHZ
|
||||
* @arg HSE_32MHZ
|
||||
* @arg SYS_PLL
|
||||
* @retval None
|
||||
*/
|
||||
void scm_setsystemclock (scm_user_id_t user_id, scm_clockconfig_t sysclockconfig);
|
||||
|
||||
/**
|
||||
* @brief Called each time the PLL is ready
|
||||
* @param None
|
||||
* @retval None
|
||||
* @note This function is defined as weak in SCM module.
|
||||
* Can be overridden by user.
|
||||
*/
|
||||
void scm_pllready(void);
|
||||
|
||||
/**
|
||||
* @brief Configure the Flash and SRAMs wait cycle (when required for system clock source change)
|
||||
* @param ws_lp_config: This parameter can be one of the following:
|
||||
* @arg LP
|
||||
* @arg RUN
|
||||
* @arg HSE16
|
||||
* @arg HSE32
|
||||
* @arg PLL
|
||||
* @retval None
|
||||
*/
|
||||
void scm_setwaitstates(const scm_ws_lp_t ws_lp_config);
|
||||
|
||||
/**
|
||||
* @brief Notify the state of the Radio
|
||||
* @param radio_state: This parameter can be one of the following:
|
||||
* @arg SCM_RADIO_ACTIVE
|
||||
* @arg SCM_RADIO_NOT_ACTIVE
|
||||
* @retval None
|
||||
*/
|
||||
void scm_notifyradiostate(const scm_radio_state_t radio_state);
|
||||
|
||||
/**
|
||||
* @brief SCM HSERDY interrupt handler.
|
||||
* Switch system clock on HSE.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void scm_hserdy_isr(void);
|
||||
|
||||
/**
|
||||
* @brief SCM PLLRDY interrupt handler.
|
||||
* Switch system clock on PLL.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void scm_pllrdy_isr(void);
|
||||
|
||||
/* SCM HSE BEGIN */
|
||||
/**
|
||||
* @brief Getter for SW HSERDY flag
|
||||
*/
|
||||
uint8_t SCM_HSE_Get_SW_HSERDY(void);
|
||||
|
||||
/**
|
||||
* @brief Setter for SW HSERDY flag
|
||||
*/
|
||||
void SCM_HSE_Set_SW_HSERDY(void);
|
||||
|
||||
/**
|
||||
* @brief Clean of SW HSERDY flag
|
||||
*/
|
||||
void SCM_HSE_Clear_SW_HSERDY(void);
|
||||
|
||||
/**
|
||||
* @brief Polling function to wait until HSE is ready
|
||||
*/
|
||||
void SCM_HSE_WaitUntilReady(void);
|
||||
|
||||
/**
|
||||
* @brief Start the HSE stabilization timer
|
||||
*/
|
||||
void SCM_HSE_StartStabilizationTimer(void);
|
||||
|
||||
/**
|
||||
* @brief Stop the HSE stabilization timer
|
||||
*/
|
||||
void SCM_HSE_StopStabilizationTimer(void);
|
||||
|
||||
/**
|
||||
* @brief HSE stabilization timer interrupt handler
|
||||
*/
|
||||
void SCM_HSE_SW_HSERDY_isr(void);
|
||||
/* SCM HSE END */
|
||||
|
||||
/* Exported functions - To be implemented by the user ------------------------- */
|
||||
|
||||
/**
|
||||
* @brief SCM HSI clock enable
|
||||
* @details A weak version is implemented in the module sources.
|
||||
* @details It can be overridden by user.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
extern void SCM_HSI_CLK_ON(void);
|
||||
|
||||
/**
|
||||
* @brief SCM HSI clock may be disabled when this function is called
|
||||
* @details A weak version is implemented in the module sources.
|
||||
* @details It can be overridden by user.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
extern void SCM_HSI_CLK_OFF(void);
|
||||
|
||||
/* SCM HSE BEGIN */
|
||||
/**
|
||||
* @brief Entry hook for HSI switch
|
||||
*/
|
||||
extern void SCM_HSI_SwithSystemClock_Entry(void);
|
||||
|
||||
/**
|
||||
* @brief Exit hook for HSI switch
|
||||
*/
|
||||
extern void SCM_HSI_SwithSystemClock_Exit(void);
|
||||
/* SCM HSE END */
|
||||
#else /* CFG_SCM_SUPPORTED */
|
||||
|
||||
/* Unused empty functions */
|
||||
void scm_hserdy_isr(void);
|
||||
void scm_pllrdy_isr(void);
|
||||
|
||||
#endif /* CFG_SCM_SUPPORTED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SCM_H */
|
||||
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm_list.c
|
||||
* @author MCD Application Team
|
||||
* @brief TCircular Linked List Implementation.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Include Files
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "stm_list.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Function Definitions
|
||||
******************************************************************************/
|
||||
void LST_init_head (tListNode * listHead)
|
||||
{
|
||||
listHead->next = listHead;
|
||||
listHead->prev = listHead;
|
||||
}
|
||||
|
||||
uint8_t LST_is_empty (tListNode * listHead)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
uint8_t return_value;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
if(listHead->next == listHead)
|
||||
{
|
||||
return_value = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = FALSE;
|
||||
}
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void LST_insert_head (tListNode * listHead, tListNode * node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
node->next = listHead->next;
|
||||
node->prev = listHead;
|
||||
listHead->next = node;
|
||||
(node->next)->prev = node;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_insert_tail (tListNode * listHead, tListNode * node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
node->next = listHead;
|
||||
node->prev = listHead->prev;
|
||||
listHead->prev = node;
|
||||
(node->prev)->next = node;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_remove_node (tListNode * node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
(node->prev)->next = node->next;
|
||||
(node->next)->prev = node->prev;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_remove_head (tListNode * listHead, tListNode ** node )
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
*node = listHead->next;
|
||||
LST_remove_node (listHead->next);
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_remove_tail (tListNode * listHead, tListNode ** node )
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
*node = listHead->prev;
|
||||
LST_remove_node (listHead->prev);
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_insert_node_after (tListNode * node, tListNode * ref_node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
node->next = ref_node->next;
|
||||
node->prev = ref_node;
|
||||
ref_node->next = node;
|
||||
(node->next)->prev = node;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_insert_node_before (tListNode * node, tListNode * ref_node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
node->next = ref_node;
|
||||
node->prev = ref_node->prev;
|
||||
ref_node->prev = node;
|
||||
(node->prev)->next = node;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
int LST_get_size (tListNode * listHead)
|
||||
{
|
||||
int size = 0;
|
||||
tListNode * temp;
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
temp = listHead->next;
|
||||
while (temp != listHead)
|
||||
{
|
||||
size++;
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
void LST_get_next_node (tListNode * ref_node, tListNode ** node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
*node = ref_node->next;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
void LST_get_prev_node (tListNode * ref_node, tListNode ** node)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
*node = ref_node->prev;
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm_list.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file for linked list library.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef STM_LIST_H
|
||||
#define STM_LIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32_wpan_common.h"
|
||||
|
||||
typedef __PACKED_STRUCT _tListNode {
|
||||
struct _tListNode * next;
|
||||
struct _tListNode * prev;
|
||||
} tListNode;
|
||||
|
||||
void LST_init_head (tListNode * listHead);
|
||||
|
||||
uint8_t LST_is_empty (tListNode * listHead);
|
||||
|
||||
void LST_insert_head (tListNode * listHead, tListNode * node);
|
||||
|
||||
void LST_insert_tail (tListNode * listHead, tListNode * node);
|
||||
|
||||
void LST_remove_node (tListNode * node);
|
||||
|
||||
void LST_remove_head (tListNode * listHead, tListNode ** node );
|
||||
|
||||
void LST_remove_tail (tListNode * listHead, tListNode ** node );
|
||||
|
||||
void LST_insert_node_after (tListNode * node, tListNode * ref_node);
|
||||
|
||||
void LST_insert_node_before (tListNode * node, tListNode * ref_node);
|
||||
|
||||
int LST_get_size (tListNode * listHead);
|
||||
|
||||
void LST_get_next_node (tListNode * ref_node, tListNode ** node);
|
||||
|
||||
void LST_get_prev_node (tListNode * ref_node, tListNode ** node);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STM_LIST_H */
|
||||
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm_queue.c
|
||||
* @author MCD Application Team
|
||||
* @brief Queue management
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
|
||||
#include "stm_queue.h"
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private typedef -------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
#define MOD(X,Y) (((X) >= (Y)) ? ((X)-(Y)) : (X))
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Public functions ----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initilialze queue structure .
|
||||
* @note This function is used to initialize the global queue structure.
|
||||
* @param q: pointer on queue structure to be initialised
|
||||
* @param queueBuffer: pointer on Queue Buffer
|
||||
* @param queueSize: Size of Queue Buffer
|
||||
* @param elementSize: Size of an element in the queue. if =0, the queue will manage variable sizze elements
|
||||
* @retval always 0
|
||||
*/
|
||||
int CircularQueue_Init(queue_t *q, uint8_t* queueBuffer, uint32_t queueSize, uint16_t elementSize, uint8_t optionFlags)
|
||||
{
|
||||
q->qBuff = queueBuffer;
|
||||
q->first = 0;
|
||||
q->last = 0; /* queueSize-1; */
|
||||
q->byteCount = 0;
|
||||
q->elementCount = 0;
|
||||
q->queueMaxSize = queueSize;
|
||||
q->elementSize = elementSize;
|
||||
q->optionFlags = optionFlags;
|
||||
|
||||
if ((optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG) && q-> elementSize)
|
||||
{
|
||||
/* can not deal with splitting at the end of buffer with fixed size element */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add element to the queue .
|
||||
* @note This function is used to add one or more element(s) to the Circular Queue .
|
||||
* @param q: pointer on queue structure to be handled
|
||||
* @param X; pointer on element(s) to be added
|
||||
* @param elementSize: Size of element to be added to the queue. Only used if the queue manage variable size elements
|
||||
* @param nbElements: number of elements in the in buffer pointed by x
|
||||
* @retval pointer on last element just added to the queue, NULL if the element to be added do not fit in the queue (too big)
|
||||
*/
|
||||
uint8_t* CircularQueue_Add(queue_t *q, uint8_t* x, uint16_t elementSize, uint32_t nbElements)
|
||||
{
|
||||
|
||||
uint8_t* ptr = NULL; /* fct return ptr to the element freshly added, if no room fct return NULL */
|
||||
uint16_t curElementSize = 0; /* the size of the element currently stored at q->last position */
|
||||
uint8_t elemSizeStorageRoom = 0 ; /* Indicate the header (which contain only size) of element in case of varaibale size element (q->elementsize == 0) */
|
||||
uint32_t curBuffPosition; /* the current position in the queue buffer */
|
||||
uint32_t i; /* loop counter */
|
||||
uint32_t NbBytesToCopy = 0, NbCopiedBytes = 0 ; /* Indicators for copying bytes in queue */
|
||||
uint32_t eob_free_size; /* Eof End of Quque Buffer Free Size */
|
||||
uint8_t wrap_will_occur = 0; /* indicate if a wrap around will occurs */
|
||||
uint8_t wrapped_element_eob_size; /* In case of Wrap around, indicate size of parta of element that fit at thened of the queuue buffer */
|
||||
uint16_t overhead = 0; /* In case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG or CIRCULAR_QUEUE_NO_WRAP_FLAG options,
|
||||
indcate the size overhead that will be generated by adding the element with wrap management (split or no wrap ) */
|
||||
|
||||
|
||||
elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
|
||||
/* retrieve the size of last element sored: the value stored at the beginning of the queue element if element size is variable otherwise take it from fixed element Size member */
|
||||
if (q->byteCount)
|
||||
{
|
||||
curElementSize = (q->elementSize == 0) ? q->qBuff[q->last] + ((q->qBuff[MOD((q->last+1), q->queueMaxSize)])<<8) + 2 : q->elementSize;
|
||||
}
|
||||
/* if queue element have fixed size , reset the elementSize arg with fixed element size value */
|
||||
if (q->elementSize > 0)
|
||||
{
|
||||
elementSize = q->elementSize;
|
||||
}
|
||||
|
||||
eob_free_size = (q->last >= q->first) ? q->queueMaxSize - (q->last + curElementSize) : 0;
|
||||
|
||||
/* check how many bytes of wrapped element (if anay) are at end of buffer */
|
||||
wrapped_element_eob_size = (((elementSize + elemSizeStorageRoom )*nbElements) < eob_free_size) ? 0 : (eob_free_size % (elementSize + elemSizeStorageRoom));
|
||||
wrap_will_occur = wrapped_element_eob_size > elemSizeStorageRoom;
|
||||
|
||||
overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)) ? wrapped_element_eob_size : overhead;
|
||||
overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)) ? elemSizeStorageRoom : overhead;
|
||||
|
||||
|
||||
/* Store now the elements if ennough room for all elements */
|
||||
if (elementSize && ((q->byteCount + ((elementSize + elemSizeStorageRoom )*nbElements) + overhead) <= q->queueMaxSize))
|
||||
{
|
||||
/* loop to add all elements */
|
||||
for (i=0; i < nbElements; i++)
|
||||
{
|
||||
q->last = MOD ((q->last + curElementSize),q->queueMaxSize);
|
||||
curBuffPosition = q->last;
|
||||
|
||||
/* store the element */
|
||||
/* store first the element size if element size is variable */
|
||||
if (q->elementSize == 0)
|
||||
{
|
||||
q->qBuff[curBuffPosition++]= elementSize & 0xFF;
|
||||
curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
|
||||
q->qBuff[curBuffPosition++]= (elementSize & 0xFF00) >> 8 ;
|
||||
curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
|
||||
q->byteCount += 2;
|
||||
}
|
||||
|
||||
/* Identify number of bytes of copy takeing account possible wrap, in this case NbBytesToCopy will contains size that fit at end of the queue buffer */
|
||||
NbBytesToCopy = MIN((q->queueMaxSize-curBuffPosition),elementSize);
|
||||
/* check if no wrap (NbBytesToCopy == elementSize) or if Wrap and no spsicf option;
|
||||
In this case part of data will copied at the end of the buffer and the rest a the beginning */
|
||||
if ((NbBytesToCopy == elementSize) || ((NbBytesToCopy < elementSize) && (q->optionFlags == CIRCULAR_QUEUE_NO_FLAG)))
|
||||
{
|
||||
/* Copy First part (or emtire buffer ) from current position up to the end of the buffer queue (or before if enough room) */
|
||||
memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
|
||||
/* Adjust bytes count */
|
||||
q->byteCount += NbBytesToCopy;
|
||||
/* Wrap */
|
||||
curBuffPosition = 0;
|
||||
/* set NbCopiedBytes bytes with ampount copied */
|
||||
NbCopiedBytes = NbBytesToCopy;
|
||||
/* set the rest to copy if wrao , if no wrap will be 0 */
|
||||
NbBytesToCopy = elementSize - NbBytesToCopy;
|
||||
/* set the current element Size, will be used to calaculate next last position at beginning of loop */
|
||||
curElementSize = (elementSize) + elemSizeStorageRoom ;
|
||||
}
|
||||
else if (NbBytesToCopy) /* We have a wrap to manage */
|
||||
{
|
||||
/* case of CIRCULAR_QUEUE_NO_WRAP_FLAG option */
|
||||
if (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)
|
||||
{
|
||||
/* if element size are variable and NO_WRAP option, Invalidate end of buffer setting 0xFFFF size*/
|
||||
if (q->elementSize == 0)
|
||||
{
|
||||
q->qBuff[curBuffPosition-2] = 0xFF;
|
||||
q->qBuff[curBuffPosition-1] = 0xFF;
|
||||
}
|
||||
q->byteCount += NbBytesToCopy; /* invalid data at the end of buffer are take into account in byteCount */
|
||||
/* No bytes coped a the end of buffer */
|
||||
NbCopiedBytes = 0;
|
||||
/* all element to be copied at the begnning of buffer */
|
||||
NbBytesToCopy = elementSize;
|
||||
/* Wrap */
|
||||
curBuffPosition = 0;
|
||||
/* if variable size element, invalidate end of buffer setting OxFFFF in element header (size) */
|
||||
if (q->elementSize == 0)
|
||||
{
|
||||
q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
|
||||
q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
|
||||
q->byteCount += 2;
|
||||
}
|
||||
|
||||
}
|
||||
/* case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG option */
|
||||
else if (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)
|
||||
{
|
||||
if (q->elementSize == 0)
|
||||
{
|
||||
/* reset the size of current element to the nb bytes fitting at the end of buffer */
|
||||
q->qBuff[curBuffPosition-2] = NbBytesToCopy & 0xFF;
|
||||
q->qBuff[curBuffPosition-1] = (NbBytesToCopy & 0xFF00) >> 8 ;
|
||||
/* copy the bytes */
|
||||
memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
|
||||
q->byteCount += NbBytesToCopy;
|
||||
/* set the number of copied bytes */
|
||||
NbCopiedBytes = NbBytesToCopy;
|
||||
/* set rest of data to be copied to begnning of buffer */
|
||||
NbBytesToCopy = elementSize - NbBytesToCopy;
|
||||
/* one element more dur to split in 2 elements */
|
||||
q->elementCount++;
|
||||
/* Wrap */
|
||||
curBuffPosition = 0;
|
||||
/* Set new size for rest of data */
|
||||
q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
|
||||
q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
|
||||
q->byteCount += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Should not occur */
|
||||
/* can not manage split Flag on Fixed size element */
|
||||
/* Buffer is corrupted */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
curElementSize = (NbBytesToCopy) + elemSizeStorageRoom ;
|
||||
q->last = 0;
|
||||
}
|
||||
|
||||
/* some remaining byte to copy */
|
||||
if (NbBytesToCopy)
|
||||
{
|
||||
memcpy(&q->qBuff[curBuffPosition],&x[(i*elementSize)+NbCopiedBytes],NbBytesToCopy);
|
||||
q->byteCount += NbBytesToCopy;
|
||||
}
|
||||
|
||||
/* One more element */
|
||||
q->elementCount++;
|
||||
}
|
||||
|
||||
ptr = q->qBuff + (MOD((q->last+elemSizeStorageRoom ),q->queueMaxSize));
|
||||
}
|
||||
/* for Breakpoint only...to remove */
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove element from the queue and copy it in provided buffer
|
||||
* @note This function is used to remove and element from the Circular Queue .
|
||||
* @param q: pointer on queue structure to be handled
|
||||
* @param elementSize: Pointer to return Size of element to be removed
|
||||
* @param buffer: destination buffer where to copy element
|
||||
* @retval Pointer on removed element. NULL if queue was empty
|
||||
*/
|
||||
uint8_t* CircularQueue_Remove_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove element from the queue.
|
||||
* @note This function is used to remove and element from the Circular Queue .
|
||||
* @param q: pointer on queue structure to be handled
|
||||
* @param elementSize: Pointer to return Size of element to be removed (ignored if NULL)
|
||||
* @retval Pointer on removed element. NULL if queue was empty
|
||||
*/
|
||||
uint8_t* CircularQueue_Remove(queue_t *q, uint16_t* elementSize)
|
||||
{
|
||||
uint8_t elemSizeStorageRoom = 0;
|
||||
uint8_t* ptr= NULL;
|
||||
elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
|
||||
uint16_t eltSize = 0;
|
||||
if (q->byteCount > 0)
|
||||
{
|
||||
/* retrieve element Size */
|
||||
eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
|
||||
|
||||
if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
|
||||
{
|
||||
if (((eltSize == 0xFFFF) && q->elementSize == 0 ) ||
|
||||
((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
|
||||
{
|
||||
/* all data from current position up to the end of buffer are invalid */
|
||||
q->byteCount -= (q->queueMaxSize - q->first);
|
||||
/* Adjust first element pos */
|
||||
q->first = 0;
|
||||
/* retrieve the right size after the wrap [if variable size element] */
|
||||
eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* retrieve element */
|
||||
ptr = q->qBuff + (MOD((q->first + elemSizeStorageRoom), q->queueMaxSize));
|
||||
|
||||
/* adjust byte count */
|
||||
q->byteCount -= (eltSize + elemSizeStorageRoom) ;
|
||||
|
||||
/* Adjust q->first */
|
||||
if (q->byteCount > 0)
|
||||
{
|
||||
q->first = MOD((q->first+ eltSize + elemSizeStorageRoom ), q->queueMaxSize);
|
||||
}
|
||||
/* adjust element count */
|
||||
--q->elementCount;
|
||||
}
|
||||
if (elementSize != NULL)
|
||||
{
|
||||
*elementSize = eltSize;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief "Sense" first element of the queue, without removing it and copy it in provided buffer
|
||||
* @note This function is used to return a pointer on the first element of the queue without removing it.
|
||||
* @param q: pointer on queue structure to be handled
|
||||
* @param elementSize: Pointer to return Size of element to be removed
|
||||
* @param buffer: destination buffer where to copy element
|
||||
* @retval Pointer on sensed element. NULL if queue was empty
|
||||
*/
|
||||
|
||||
uint8_t* CircularQueue_Sense_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief "Sense" first element of the queue, without removing it.
|
||||
* @note This function is used to return a pointer on the first element of the queue without removing it.
|
||||
* @param q: pointer on queue structure to be handled
|
||||
* @param elementSize: Pointer to return Size of element to be removed (ignored if NULL)
|
||||
* @retval Pointer on sensed element. NULL if queue was empty
|
||||
*/
|
||||
uint8_t* CircularQueue_Sense(queue_t *q, uint16_t* elementSize)
|
||||
{
|
||||
uint8_t elemSizeStorageRoom = 0;
|
||||
uint8_t* x= NULL;
|
||||
elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
|
||||
uint16_t eltSize = 0;
|
||||
uint32_t FirstElemetPos = 0;
|
||||
|
||||
if (q->byteCount > 0)
|
||||
{
|
||||
FirstElemetPos = q->first;
|
||||
eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
|
||||
|
||||
if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
|
||||
{
|
||||
if (((eltSize == 0xFFFF) && q->elementSize == 0 ) ||
|
||||
((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
|
||||
|
||||
{
|
||||
/* all data from current position up to the end of buffer are invalid */
|
||||
FirstElemetPos = 0; /* wrap to the begiining of buffer */
|
||||
|
||||
/* retrieve the right size after the wrap [if variable size element] */
|
||||
eltSize = (q->elementSize == 0) ? q->qBuff[FirstElemetPos]+ ((q->qBuff[MOD((FirstElemetPos+1), q->queueMaxSize)])<<8) : q->elementSize;
|
||||
}
|
||||
}
|
||||
/* retrieve element */
|
||||
x = q->qBuff + (MOD((FirstElemetPos + elemSizeStorageRoom), q->queueMaxSize));
|
||||
}
|
||||
if (elementSize != NULL)
|
||||
{
|
||||
*elementSize = eltSize;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if queue is empty.
|
||||
* @note This function is used to to check if the queue is empty.
|
||||
* @param q: pointer on queue structure to be handled
|
||||
* @retval TRUE (!0) if the queue is empyu otherwise FALSE (0)
|
||||
*/
|
||||
int CircularQueue_Empty(queue_t *q)
|
||||
{
|
||||
int ret=FALSE;
|
||||
if (q->byteCount <= 0)
|
||||
{
|
||||
ret=TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CircularQueue_NbElement(queue_t *q)
|
||||
{
|
||||
return q->elementCount;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm_queue.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for stm_queue.c
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM_QUEUE_H
|
||||
#define __STM_QUEUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported define -----------------------------------------------------------*/
|
||||
/* Options flags */
|
||||
#define CIRCULAR_QUEUE_NO_FLAG 0
|
||||
#define CIRCULAR_QUEUE_NO_WRAP_FLAG 1
|
||||
#define CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG 2
|
||||
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
uint8_t* qBuff; /* queue buffer, , provided by init fct */
|
||||
uint32_t queueMaxSize; /* size of the queue, provided by init fct (in bytes)*/
|
||||
uint16_t elementSize; /* -1 variable. If variable element size the size is stored in the 4 first of the queue element */
|
||||
uint32_t first; /* position of first element */
|
||||
uint32_t last; /* position of last element */
|
||||
uint32_t byteCount; /* number of bytes in the queue */
|
||||
uint32_t elementCount; /* number of element in the queue */
|
||||
uint8_t optionFlags; /* option to enable specific features */
|
||||
} queue_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
int CircularQueue_Init(queue_t *q, uint8_t* queueBuffer, uint32_t queueSize, uint16_t elementSize, uint8_t optionlags);
|
||||
uint8_t* CircularQueue_Add(queue_t *q, uint8_t* x, uint16_t elementSize, uint32_t nbElements);
|
||||
uint8_t* CircularQueue_Remove(queue_t *q, uint16_t* elementSize);
|
||||
uint8_t* CircularQueue_Sense(queue_t *q, uint16_t* elementSize);
|
||||
int CircularQueue_Empty(queue_t *q);
|
||||
int CircularQueue_NbElement(queue_t *q);
|
||||
uint8_t* CircularQueue_Remove_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer);
|
||||
uint8_t* CircularQueue_Sense_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer);
|
||||
|
||||
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM_QUEUE_H */
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file temp_measurement.c
|
||||
* @author MCD Application Team
|
||||
* @brief Temp measurement module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* Common utilites */
|
||||
#include "utilities_common.h"
|
||||
|
||||
#if (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1)
|
||||
/* Own header file */
|
||||
#include "temp_measurement.h"
|
||||
/* ADC Controller module */
|
||||
#include "adc_ctrl.h"
|
||||
#include "adc_ctrl_conf.h"
|
||||
|
||||
/* Link layer interfaces */
|
||||
#include "ll_intf.h"
|
||||
#include "ll_intf_cmn.h"
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Error Handler */
|
||||
extern void Error_Handler(void);
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
TEMPMEAS_Cmd_Status_t TEMPMEAS_Init (void)
|
||||
{
|
||||
TEMPMEAS_Cmd_Status_t error = TEMPMEAS_UNKNOWN;
|
||||
|
||||
ADCCTRL_Cmd_Status_t eReturn = ADCCTRL_UNKNOWN;
|
||||
|
||||
eReturn = ADCCTRL_RegisterHandle (&LLTempRequest_Handle);
|
||||
|
||||
if ((ADCCTRL_HANDLE_ALREADY_REGISTERED == eReturn) ||
|
||||
(ADCCTRL_OK == eReturn))
|
||||
{
|
||||
error = TEMPMEAS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = TEMPMEAS_ADC_INIT;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void TEMPMEAS_RequestTemperatureMeasurement (void)
|
||||
{
|
||||
int16_t temperature_value = 0;
|
||||
|
||||
/* Enter limited critical section : disable all the interrupts with priority higher than RCC one
|
||||
* Concerns link layer interrupts (high and SW low) or any other high priority user system interrupt
|
||||
*/
|
||||
UTILS_ENTER_LIMITED_CRITICAL_SECTION(RCC_INTR_PRIO<<4);
|
||||
|
||||
/* Request ADC IP activation */
|
||||
ADCCTRL_RequestIpState(&LLTempRequest_Handle, ADC_ON);
|
||||
|
||||
/* Get temperature from ADC dedicated channel */
|
||||
ADCCTRL_RequestTemperature (&LLTempRequest_Handle,
|
||||
&temperature_value);
|
||||
|
||||
/* Request ADC IP deactivation */
|
||||
ADCCTRL_RequestIpState(&LLTempRequest_Handle, ADC_OFF);
|
||||
|
||||
/* Give shifted value of the temperature to the link layer */
|
||||
ll_intf_cmn_set_temperature_value((uint32_t)(temperature_value + TEMPMEAS_MIN_TEMP_LIMIT));
|
||||
|
||||
/* Exit limited critical section */
|
||||
UTILS_EXIT_LIMITED_CRITICAL_SECTION();
|
||||
}
|
||||
#endif /* USE_TEMPERATURE_BASED_RADIO_CALIBRATION */
|
||||
/* Private Functions Definition ------------------------------------------------------*/
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file temp_measurement.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for temp_measurement.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef TEMP_MEASUREMENT_H
|
||||
#define TEMP_MEASUREMENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "utilities_common.h"
|
||||
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Minimum operating temperature limit absolute value
|
||||
*
|
||||
* @details I.e.: Operating temperature is between -40C and 105degC,
|
||||
* Minimum value expected is 40u.
|
||||
*/
|
||||
#define TEMPMEAS_MIN_TEMP_LIMIT ((uint32_t)40u)
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Temperature Measurement command status codes
|
||||
*/
|
||||
typedef enum TEMPMEAS_Cmd_Status
|
||||
{
|
||||
TEMPMEAS_OK,
|
||||
TEMPMEAS_NOK,
|
||||
TEMPMEAS_ADC_INIT,
|
||||
TEMPMEAS_UNKNOWN,
|
||||
} TEMPMEAS_Cmd_Status_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the temperature measurement
|
||||
*
|
||||
* @retval Operation state
|
||||
*/
|
||||
TEMPMEAS_Cmd_Status_t TEMPMEAS_Init (void);
|
||||
|
||||
/**
|
||||
* @brief Request temperature measurement
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void TEMPMEAS_RequestTemperatureMeasurement (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEMP_MEASUREMENT_H */
|
||||
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file utilities_common.h
|
||||
* @author MCD Application Team
|
||||
* @brief Common file to utilities
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef UTILITIES_COMMON_H
|
||||
#define UTILITIES_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
/* -------------------------------- *
|
||||
* Basic definitions *
|
||||
* -------------------------------- */
|
||||
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
|
||||
#undef FALSE
|
||||
#define FALSE 0
|
||||
|
||||
#undef TRUE
|
||||
#define TRUE (!0)
|
||||
|
||||
/* -------------------------------- *
|
||||
* Critical Section definition *
|
||||
* -------------------------------- */
|
||||
#undef BACKUP_PRIMASK
|
||||
#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK()
|
||||
|
||||
#undef DISABLE_IRQ
|
||||
#define DISABLE_IRQ() __disable_irq()
|
||||
|
||||
#undef RESTORE_PRIMASK
|
||||
#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit)
|
||||
|
||||
/* -------------------------------- *
|
||||
* Macro delimiters *
|
||||
* -------------------------------- */
|
||||
#undef M_BEGIN
|
||||
#define M_BEGIN do {
|
||||
|
||||
#undef M_END
|
||||
#define M_END } while(0)
|
||||
|
||||
/* -------------------------------- *
|
||||
* Some useful macro definitions *
|
||||
* -------------------------------- */
|
||||
#undef MAX
|
||||
#define MAX( x, y ) (((x)>(y))?(x):(y))
|
||||
|
||||
#undef MIN
|
||||
#define MIN( x, y ) (((x)<(y))?(x):(y))
|
||||
|
||||
#undef MODINC
|
||||
#define MODINC( a, m ) M_BEGIN (a)++; if ((a)>=(m)) (a)=0; M_END
|
||||
|
||||
#undef MODDEC
|
||||
#define MODDEC( a, m ) M_BEGIN if ((a)==0) (a)=(m); (a)--; M_END
|
||||
|
||||
#undef MODADD
|
||||
#define MODADD( a, b, m ) M_BEGIN (a)+=(b); if ((a)>=(m)) (a)-=(m); M_END
|
||||
|
||||
#undef MODSUB
|
||||
#define MODSUB( a, b, m ) MODADD( a, (m)-(b), m )
|
||||
|
||||
#undef ALIGN
|
||||
#ifdef WIN32
|
||||
#define ALIGN(n)
|
||||
#else
|
||||
#define ALIGN(n) __attribute__((aligned(n)))
|
||||
#endif
|
||||
|
||||
#undef PAUSE
|
||||
#define PAUSE( t ) M_BEGIN \
|
||||
volatile int _i; \
|
||||
for ( _i = t; _i > 0; _i -- ); \
|
||||
M_END
|
||||
#undef DIVF
|
||||
#define DIVF( x, y ) ((x)/(y))
|
||||
|
||||
#undef DIVC
|
||||
#define DIVC( x, y ) (((x)+(y)-1)/(y))
|
||||
|
||||
#undef DIVR
|
||||
#define DIVR( x, y ) (((x)+((y)/2))/(y))
|
||||
|
||||
#undef SHRR
|
||||
#define SHRR( x, n ) ((((x)>>((n)-1))+1)>>1)
|
||||
|
||||
#undef BITN
|
||||
#define BITN( w, n ) (((w)[(n)/32] >> ((n)%32)) & 1)
|
||||
|
||||
#undef BITNSET
|
||||
#define BITNSET( w, n, b ) M_BEGIN (w)[(n)/32] |= ((U32)(b))<<((n)%32); M_END
|
||||
|
||||
/* -------------------------------- *
|
||||
* Section attribute *
|
||||
* -------------------------------- */
|
||||
#define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SYS_WAITING_CYCLES_25() do {\
|
||||
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
|
||||
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
|
||||
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
|
||||
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
|
||||
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
|
||||
} while(0)
|
||||
|
||||
#define SYS_WAITING_RNGCLK_DEACTIVATION() do {\
|
||||
for(volatile unsigned int cpt = 178 ; cpt!=0 ; --cpt);\
|
||||
} while(0)
|
||||
|
||||
#define STM32WBA5x_DEFAULT_SCA_RANGE (0)
|
||||
#define STM32WBA5x_REV_ID_A_SCA_RANGE (0)
|
||||
#define STM32WBA5x_REV_ID_B_SCA_RANGE (0)
|
||||
#ifdef STM32WBA65xx
|
||||
#define STM32WBA6x_SCA_RANGE (0)
|
||||
#endif
|
||||
|
||||
/* Macro helper for optimizing by speed specific functions.
|
||||
* For IAR only: The functions with this definition will be optimized
|
||||
* by speed only if the project uses a High optimisation level.
|
||||
*/
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
#define OPTIMIZED _Pragma("optimize=speed")
|
||||
#elif defined(__clang__)
|
||||
#define OPTIMIZED _Pragma("pragma Ofast")
|
||||
#elif defined(__GNUC__)
|
||||
#define OPTIMIZED __attribute__((optimize("Ofast")))
|
||||
#endif
|
||||
|
||||
#define UTIL_UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
|
||||
|
||||
#endif /* UTILITIES_COMMON_H */
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
;********************************************************************************
|
||||
;* File Name : stm32wbaxx_ResetHandler.s
|
||||
;* Author : MCD Application Team
|
||||
;* Description : STM32WBA5xx Ultra Low Power Devices specific
|
||||
; Reset handler for connectivity applications.
|
||||
; EWARM toolchain.
|
||||
;********************************************************************************
|
||||
;* @attention
|
||||
;*
|
||||
;* Copyright (c) 2022 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.
|
||||
;*
|
||||
;*******************************************************************************
|
||||
;
|
||||
; Cortex-M version
|
||||
;
|
||||
EXTERN __iar_program_start
|
||||
EXTERN SystemInit
|
||||
EXTERN is_boot_from_standby
|
||||
EXTERN SYS_WAITING_CYCLES_25
|
||||
|
||||
IMPORT backup_MSP
|
||||
IMPORT register_backup_table
|
||||
IMPORT register_backup_table_size
|
||||
|
||||
EXPORT CPUcontextSave
|
||||
EXPORT backup_system_register
|
||||
EXPORT restore_system_register
|
||||
|
||||
PUBLIC Reset_Handler
|
||||
SECTION .text:CODE:NOROOT:REORDER(2)
|
||||
Reset_Handler
|
||||
/* If we exit from standby mode, restore CPU context and jump to asleep point. */
|
||||
BL is_boot_from_standby
|
||||
CMP R0, #1
|
||||
BEQ CPUcontextRestore
|
||||
/* buffer for local variables (up to 10)from is_boot_from_standby*/
|
||||
SUB SP, SP, #0x28
|
||||
/* end of specific code section for standby */
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__iar_program_start
|
||||
BX R0
|
||||
|
||||
/* These 2 functions are designed to save and then restore CPU context. */
|
||||
CPUcontextSave
|
||||
PUSH { R4 - R12, LR } /* store R4 to R12 and LR (10 words) onto C stack */
|
||||
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
|
||||
MOV R3, SP /* load the stack pointer into R3 */
|
||||
STR R3, [R4] /* store the MSP into backup_MSP */
|
||||
DSB
|
||||
WFI /* all saved, trigger deep sleep */
|
||||
|
||||
CPUcontextRestore
|
||||
/* Even if we fall through the WFI instruction, we will immediately
|
||||
* execute a context restore and end up where we left off with no
|
||||
* ill effects. Normally at this point the core will either be
|
||||
* powered off or reset (depending on the deep sleep level). */
|
||||
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
|
||||
LDR R4, [R4] /* load the SP from backup_MSP */
|
||||
MOV SP, R4 /* restore the SP from R4 */
|
||||
POP { R4 - R12, PC } /* load R4 to R12 and PC (10 words) from C stack */
|
||||
|
||||
backup_system_register
|
||||
/* R0 -> register_backup_table array current item address */
|
||||
/* R1 -> loop counter (from register_backup_table_size to 0) */
|
||||
/* R2 -> register_backup_table array current item value */
|
||||
|
||||
backup_loop_init:
|
||||
LDR R0, =register_backup_table /* R0 points to the first array item */
|
||||
LDR R1, =register_backup_table_size
|
||||
LDR R1, [R1] /* R1 contains the number of registers in the array */
|
||||
|
||||
backup_loop_iter:
|
||||
/* Offset processing */
|
||||
LDR R2, [R0], #4 /* R2 contains the register_backup_table current item (register address) */
|
||||
/* R0 points to the next register_backup_table item (uint32_t items -> 4 bytes added to previous address) */
|
||||
|
||||
/* Register value backup */
|
||||
LDR R2, [R2] /* R2 contains now the register value to backup */
|
||||
PUSH {R2} /* Push register value into the stack */
|
||||
|
||||
/* Loop iteration control */
|
||||
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
|
||||
BNE backup_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
|
||||
|
||||
backup_loop_end:
|
||||
BX LR /* Return to caller */
|
||||
|
||||
restore_system_register
|
||||
/* R0 -> register_backup_table array current item address */
|
||||
/* R1 -> loop counter (from register_backup_table_size to 0) */
|
||||
/* R2 -> register_backup_table array current item value */
|
||||
|
||||
restore_loop_init:
|
||||
LDR R0, =register_backup_table /* R0 points to the first array item */
|
||||
|
||||
/* Reverse loop: counter initial value processing */
|
||||
LDR R1, =register_backup_table_size
|
||||
LDR R1, [R1] /* R1 contains the number of registers in the array */
|
||||
SUB R1, #1 /* R1 now contains last array item index (register_backup_table_size - 1) */
|
||||
|
||||
/* Reverse loop: apply offset to current array index (point to last array element) */
|
||||
ADD R0, R1, LSL #2 /* R0 now points to last array item (register_backup_table + (register_backup_table_size - 1) * 4) */
|
||||
|
||||
ADD R1, #1 /* Re-add 1 to R1 (array length) */
|
||||
|
||||
/* Reverse loop */
|
||||
restore_loop_iter:
|
||||
/* Offset processing */
|
||||
LDR R2, [R0], #-4 /* R2 contains the register_backup_table current item (register address) */
|
||||
/* R0 now points to the previous register_backup_table item (uint32_t items -> 4 bytes subtracted to previous address) */
|
||||
|
||||
/* Register value restoration */
|
||||
POP {R3} /* Head of stack popped into R3. R3 contains register value to restore */
|
||||
STR R3, [R2] /* Write backuped value into the register */
|
||||
|
||||
/* Loop iteration control */
|
||||
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
|
||||
BNE restore_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
|
||||
|
||||
restore_loop_end:
|
||||
BX LR /* Return to caller */
|
||||
|
||||
/* end of specific code section for standby */
|
||||
|
||||
END
|
||||
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : stm32wbaxx_ResetHandler.s
|
||||
* Author : MCD Application Team
|
||||
* Description : STM32WBA5xx Ultra Low Power Devices specific
|
||||
* Reset handler for connectivity applications.
|
||||
GCC toolchain.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* Cortex-M version
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m33
|
||||
.fpu softvfp
|
||||
.thumb
|
||||
|
||||
.extern SystemInit
|
||||
.extern is_boot_from_standby
|
||||
.extern SYS_WAITING_CYCLES_25
|
||||
|
||||
.global backup_system_register
|
||||
.global restore_system_register
|
||||
|
||||
/* INIT_BSS macro is used to fill the specified region [start : end] with zeros */
|
||||
.macro INIT_BSS start, end
|
||||
ldr r0, =\start
|
||||
ldr r1, =\end
|
||||
movs r3, #0
|
||||
bl LoopFillZerobss
|
||||
.endm
|
||||
|
||||
/* INIT_DATA macro is used to copy data in the region [start : end] starting from 'src' */
|
||||
.macro INIT_DATA start, end, src
|
||||
ldr r0, =\start
|
||||
ldr r1, =\end
|
||||
ldr r2, =\src
|
||||
movs r3, #0
|
||||
bl LoopCopyDataInit
|
||||
.endm
|
||||
|
||||
.section .text.data_initializers
|
||||
CopyDataInit:
|
||||
ldr r4, [r2, r3]
|
||||
str r4, [r0, r3]
|
||||
adds r3, r3, #4
|
||||
|
||||
LoopCopyDataInit:
|
||||
adds r4, r0, r3
|
||||
cmp r4, r1
|
||||
bcc CopyDataInit
|
||||
bx lr
|
||||
|
||||
FillZerobss:
|
||||
str r3, [r0]
|
||||
adds r0, r0, #4
|
||||
|
||||
LoopFillZerobss:
|
||||
cmp r0, r1
|
||||
bcc FillZerobss
|
||||
bx lr
|
||||
|
||||
.section .text.Reset_Handler
|
||||
.global Reset_Handler
|
||||
.type Reset_Handler, %function
|
||||
Reset_Handler:
|
||||
ldr r0, =_estack
|
||||
mov sp, r0 /* set stack pointer */
|
||||
/* If we exit from standby mode, restore CPU context and jump to asleep point. */
|
||||
BL is_boot_from_standby
|
||||
CMP R0, #1
|
||||
BEQ CPUcontextRestore
|
||||
/* buffer for local variables (up to 10)from is_boot_from_standby*/
|
||||
SUB SP, SP, #0x28
|
||||
/* end of specific code section for standby */
|
||||
/* Call the clock system initialization function.*/
|
||||
bl SystemInit
|
||||
|
||||
/* Copy the data segment initializers from flash to SRAM */
|
||||
INIT_DATA _sdata, _edata, _sidata
|
||||
|
||||
/* Zero fill the bss segments. */
|
||||
INIT_BSS _sbss, _ebss
|
||||
|
||||
/* Call static constructors */
|
||||
bl __libc_init_array
|
||||
/* Call the application s entry point.*/
|
||||
bl main
|
||||
|
||||
LoopForever:
|
||||
b LoopForever
|
||||
|
||||
/* These 2 functions are designed to save and then restore CPU context. */
|
||||
.global CPUcontextSave
|
||||
.type CPUcontextSave, %function
|
||||
CPUcontextSave:
|
||||
PUSH { R4 - R12, LR } /* store R4 to R12 and LR (10 words) onto C stack */
|
||||
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
|
||||
MOV R3, SP /* load the stack pointer into R3 */
|
||||
STR R3, [R4] /* store the MSP into backup_MSP */
|
||||
DSB
|
||||
WFI /* all saved, trigger deep sleep */
|
||||
|
||||
CPUcontextRestore:
|
||||
/* Even if we fall through the WFI instruction, we will immediately
|
||||
* execute a context restore and end up where we left off with no
|
||||
* ill effects. Normally at this point the core will either be
|
||||
* powered off or reset (depending on the deep sleep level). */
|
||||
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
|
||||
LDR R4, [R4] /* load the SP from backup_MSP */
|
||||
MOV SP, R4 /* restore the SP from R4 */
|
||||
POP { R4 - R12, PC } /* load R4 to R12 and PC (10 words) from C stack */
|
||||
|
||||
backup_system_register:
|
||||
/* R0 -> register_backup_table array current item address */
|
||||
/* R1 -> loop counter (from register_backup_table_size to 0) */
|
||||
/* R2 -> register_backup_table array current item value */
|
||||
|
||||
backup_loop_init:
|
||||
LDR R0, =register_backup_table /* R0 points to the first array item */
|
||||
LDR R1, =register_backup_table_size
|
||||
LDR R1, [R1] /* R1 contains the number of registers in the array */
|
||||
|
||||
backup_loop_iter:
|
||||
/* Offset processing */
|
||||
LDR R2, [R0], #4 /* R2 contains the register_backup_table current item (register address) */
|
||||
/* R0 points to the next register_backup_table item (uint32_t items -> 4 bytes added to previous address) */
|
||||
|
||||
/* Register value backup */
|
||||
LDR R2, [R2] /* R2 contains now the register value to backup */
|
||||
PUSH {R2} /* Push register value into the stack */
|
||||
|
||||
/* Loop iteration control */
|
||||
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
|
||||
BNE backup_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
|
||||
|
||||
backup_loop_end:
|
||||
BX LR /* Return to caller */
|
||||
|
||||
restore_system_register:
|
||||
/* R0 -> register_backup_table array current item address */
|
||||
/* R1 -> loop counter (from register_backup_table_size to 0) */
|
||||
/* R2 -> register_backup_table array current item value */
|
||||
|
||||
restore_loop_init:
|
||||
LDR R0, =register_backup_table /* R0 points to the first array item */
|
||||
|
||||
/* Reverse loop: counter initial value processing */
|
||||
LDR R1, =register_backup_table_size
|
||||
LDR R1, [R1] /* R1 contains the number of registers in the array */
|
||||
SUB R1, #1 /* R1 now contains last array item index (register_backup_table_size - 1) */
|
||||
|
||||
/* Reverse loop: apply offset to current array index (point to last array element) */
|
||||
LSL R1, #2 /* Left shift R1 by 2 */
|
||||
ADD R0, R1 /* R0 now points to last array item (register_backup_table + (register_backup_table_size - 1) * 4) */
|
||||
|
||||
LSR R1, #2 /* Reverse left shift operation on R1 */
|
||||
ADD R1, #1 /* Re-add 1 to R1 (array length) */
|
||||
|
||||
/* Reverse loop */
|
||||
restore_loop_iter:
|
||||
/* Offset processing */
|
||||
LDR R2, [R0], #-4 /* R2 contains the register_backup_table current item (register address) */
|
||||
/* R0 now points to the previous register_backup_table item (uint32_t items -> 4 bytes subtracted to previous address) */
|
||||
|
||||
/* Register value restoration */
|
||||
POP {R3} /* Head of stack popped into R3. R3 contains register value to restore */
|
||||
STR R3, [R2] /* Write backuped value into the register */
|
||||
|
||||
/* Loop iteration control */
|
||||
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
|
||||
BNE restore_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
|
||||
|
||||
restore_loop_end:
|
||||
BX LR /* Return to caller */
|
||||
/* end of specific code section for standby */
|
||||
.end
|
||||
@@ -0,0 +1,134 @@
|
||||
;********************************************************************************
|
||||
;* File Name : stm32wbaxx_ResetHandler.s
|
||||
;* Author : MCD Application Team
|
||||
;* Description : STM32WBA5xx Ultra Low Power Devices specific
|
||||
; Reset handler for connectivity applications.
|
||||
; MDK-ARM toolchain.
|
||||
;********************************************************************************
|
||||
;* @attention
|
||||
;*
|
||||
;* Copyright (c) 2022 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.
|
||||
;*
|
||||
;*******************************************************************************
|
||||
;
|
||||
; Cortex-M version
|
||||
;
|
||||
PRESERVE8
|
||||
THUMB
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
; Reset_Handler
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler
|
||||
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
IMPORT is_boot_from_standby
|
||||
IMPORT backup_MSP
|
||||
IMPORT register_backup_table
|
||||
IMPORT register_backup_table_size
|
||||
|
||||
EXPORT CPUcontextSave
|
||||
EXPORT backup_system_register
|
||||
EXPORT restore_system_register
|
||||
; If we exit from standby mode, restore CPU context and jump to asleep point.
|
||||
BL is_boot_from_standby
|
||||
CMP R0, #1
|
||||
BEQ CPUcontextRestore
|
||||
; buffer for local variables (up to 10)from is_boot_from_standby.
|
||||
SUB SP, SP, #0x28
|
||||
; end of specific code section for standby
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
; These 2 functions are designed to save and then restore CPU context.
|
||||
CPUcontextSave
|
||||
PUSH { R4 - R12, lr } ; store R4 to R12 and LR (10 words) onto C stack
|
||||
LDR R4, =backup_MSP ; load address of backup_MSP into R4
|
||||
MOV R3, SP ; load the stack pointer into R3
|
||||
STR R3, [R4] ; store the MSP into backup_MSP
|
||||
DSB
|
||||
WFI ; all saved, trigger deep sleep
|
||||
|
||||
CPUcontextRestore
|
||||
; Even if we fall through the WFI instruction, we will immediately
|
||||
; execute a context restore and end up where we left off with no
|
||||
; ill effects. Normally at this point the core will either be
|
||||
; powered off or reset (depending on the deep sleep level).
|
||||
LDR R4, =backup_MSP ; load address of backup_MSP into R4.
|
||||
LDR R4, [R4] ; load the SP from backup_MSP.
|
||||
MOV SP, R4 ; restore the SP from R4.
|
||||
POP { R4 - R12, PC } ; load R4-R12 and PC (10 words) from C stack
|
||||
; end of specific code section for standby.
|
||||
|
||||
backup_system_register
|
||||
; R0 -> register_backup_table array current item address
|
||||
; R1 -> loop counter (from register_backup_table_size to 0)
|
||||
; R2 -> register_backup_table array current item value
|
||||
|
||||
backup_loop_init
|
||||
LDR R0, =register_backup_table ; R0 points to the first array item
|
||||
LDR R1, =register_backup_table_size
|
||||
LDR R1, [R1] ; R1 contains the number of registers in the array
|
||||
|
||||
backup_loop_iter
|
||||
; Offset processing
|
||||
LDR R2, [R0], #4 ; R2 contains the register_backup_table current item (register address)
|
||||
; R0 points to the next register_backup_table item (uint32_t items -> 4 bytes added to previous address)
|
||||
|
||||
; Register value backup
|
||||
LDR R2, [R2] ; R2 contains now the register value to backup
|
||||
PUSH {R2} ; Push register value into the stack
|
||||
|
||||
; Loop iteration control
|
||||
SUBS R1, #1 ; Decrement loop counter by 1 and update APSR (Application Processor Status Register)
|
||||
BNE backup_loop_iter ; Loop continues until Z flag is set (still array item to handle)
|
||||
|
||||
backup_loop_end
|
||||
BX LR ; Return to caller
|
||||
|
||||
restore_system_register
|
||||
; R0 -> register_backup_table array current item address
|
||||
; R1 -> loop counter (from register_backup_table_size to 0)
|
||||
; R2 -> register_backup_table array current item value
|
||||
|
||||
restore_loop_init
|
||||
LDR R0, =register_backup_table ; R0 points to the first array item
|
||||
|
||||
; Reverse loop: counter initial value processing
|
||||
LDR R1, =register_backup_table_size
|
||||
LDR R1, [R1] ; R1 contains the number of registers in the array
|
||||
SUB R1, #1 ; R1 now contains last array item index (register_backup_table_size - 1)
|
||||
|
||||
; Reverse loop: apply offset to current array index (point to last array element)
|
||||
ADD R0, R1, LSL #2 ; R0 now points to last array item (register_backup_table + (register_backup_table_size - 1) * 4)
|
||||
|
||||
ADD R1, #1 ; Re-add 1 to R1 (array length)
|
||||
|
||||
; Reverse loop
|
||||
restore_loop_iter
|
||||
; Offset processing
|
||||
LDR R2, [R0], #-4 ; R2 contains the register_backup_table current item (register address)
|
||||
; R0 now points to the previous register_backup_table item (uint32_t items -> 4 bytes subtracted to previous address)
|
||||
|
||||
; Register value restoration
|
||||
POP {R3} ; Head of stack popped into R3. R3 contains register value to restore
|
||||
STR R3, [R2] ; Write backuped value into the register
|
||||
|
||||
; Loop iteration control
|
||||
SUBS R1, #1 ; Decrement loop counter by 1 and update APSR (Application Processor Status Register)
|
||||
BNE restore_loop_iter ; Loop continues until Z flag is set (still array item to handle)
|
||||
|
||||
restore_loop_end
|
||||
BX LR ; Return to caller
|
||||
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user