summaryrefslogtreecommitdiff
path: root/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src
diff options
context:
space:
mode:
authorAnson Bridges <bridges.anson@gmail.com>2026-02-17 11:37:50 -0800
committerAnson Bridges <bridges.anson@gmail.com>2026-02-17 11:37:50 -0800
commitfb1611c0ca99d9e609057c46507be2af8389bb7b (patch)
tree646ac568fdad1e6cf9e1f5767295b183bc5c5441 /firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src
parent6e952fe110c2a48204c8cb0a836309ab97e5979a (diff)
firmware coadHEADmaster
Diffstat (limited to 'firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src')
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal.c852
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c505
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma.c1120
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma_ex.c295
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c634
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c743
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c1061
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_gpio.c551
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_hsem.c369
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c.c7561
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c_ex.c354
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_ipcc.c755
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c742
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c1368
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c1824
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc_ex.c2328
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc.c1945
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c2104
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi.c4481
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi_ex.c112
-rw-r--r--firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c1361
21 files changed, 31065 insertions, 0 deletions
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal.c
new file mode 100644
index 0000000..c848af1
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal.c
@@ -0,0 +1,852 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal.c
+ * @author MCD Application Team
+ * @brief HAL module driver.
+ * This is the common part of the HAL initialization
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The common HAL driver contains a set of generic and common APIs that can be
+ used by the PPP peripheral drivers and the user to start using the HAL.
+ [..]
+ The HAL contains two APIs' categories:
+ (+) Common HAL APIs
+ (+) Services HAL APIs
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup HAL
+ * @brief HAL module driver
+ * @{
+ */
+
+#ifdef HAL_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup HAL_Private_Constants HAL Private Constants
+ * @{
+ */
+/**
+ * @brief STM32WBxx HAL Driver version number
+ */
+#define __STM32WBxx_HAL_VERSION_MAIN (0x01U) /*!< [31:24] main version */
+#define __STM32WBxx_HAL_VERSION_SUB1 (0x0EU) /*!< [23:16] sub1 version */
+#define __STM32WBxx_HAL_VERSION_SUB2 (0x06U) /*!< [15:8] sub2 version */
+#define __STM32WBxx_HAL_VERSION_RC (0x00U) /*!< [7:0] release candidate */
+#define __STM32WBxx_HAL_VERSION ((__STM32WBxx_HAL_VERSION_MAIN << 24U)\
+ |(__STM32WBxx_HAL_VERSION_SUB1 << 16U)\
+ |(__STM32WBxx_HAL_VERSION_SUB2 << 8U )\
+ |(__STM32WBxx_HAL_VERSION_RC))
+
+#if defined(VREFBUF)
+#define VREFBUF_TIMEOUT_VALUE 10U /* 10 ms */
+#endif /* VREFBUF */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Exported variables ---------------------------------------------------------*/
+/** @defgroup HAL_Exported_Variables HAL Exported Variables
+ * @{
+ */
+__IO uint32_t uwTick;
+uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* Invalid PRIO */
+HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup HAL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup HAL_Exported_Functions_Group1
+ * @brief HAL Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the Flash interface the NVIC allocation and initial time base
+ clock configuration.
+ (+) De-initialize common part of the HAL.
+ (+) Configure the time base source to have 1ms time base with a dedicated
+ Tick interrupt priority.
+ (++) SysTick timer is used by default as source of time base, but user
+ can eventually implement his proper time base source (a general purpose
+ timer for example or other time source), keeping in mind that Time base
+ duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
+ handled in milliseconds basis.
+ (++) Time base configuration function (HAL_InitTick ()) is called automatically
+ at the beginning of the program after reset by HAL_Init() or at any time
+ when clock is configured, by HAL_RCC_ClockConfig().
+ (++) Source of time base is configured to generate interrupts at regular
+ time intervals. Care must be taken if HAL_Delay() is called from a
+ peripheral ISR process, the Tick interrupt line must have higher priority
+ (numerically lower) than the peripheral interrupt. Otherwise the caller
+ ISR process will be blocked.
+ (++) functions affecting time base configurations are declared as __weak
+ to make override possible in case of other implementations in user file.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function is used to initialize the HAL Library; it must be the first
+ * instruction to be executed in the main program (before to call any other
+ * HAL function), it performs the following:
+ * Configure the Flash prefetch, instruction and Data caches.
+ * Configures the SysTick to generate an interrupt each 1 millisecond,
+ * which is clocked by the MSI (at this stage, the clock is not yet
+ * configured and thus the system is running from the internal MSI at 4 MHz).
+ * Set NVIC Group Priority to 4.
+ * Calls the HAL_MspInit() callback function defined in user file
+ * "stm32wbxx_hal_msp.c" to do the global low level hardware initialization
+ *
+ * @note SysTick is used as time base for the HAL_Delay() function, the application
+ * need to ensure that the SysTick time base is always set to 1 millisecond
+ * to have correct HAL operation.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_Init(void)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ /* Configure Flash prefetch, Instruction cache, Data cache */
+ /* Default configuration at reset is: */
+ /* - Prefetch disabled */
+ /* - Instruction cache enabled */
+ /* - Data cache enabled */
+#if (INSTRUCTION_CACHE_ENABLE == 0U)
+ __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+#endif /* INSTRUCTION_CACHE_ENABLE */
+
+#if (DATA_CACHE_ENABLE == 0U)
+ __HAL_FLASH_DATA_CACHE_DISABLE();
+#endif /* DATA_CACHE_ENABLE */
+
+#if (PREFETCH_ENABLE != 0U)
+ __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
+#endif /* PREFETCH_ENABLE */
+
+ /* Set Interrupt Group Priority */
+ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
+
+ /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
+ if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Init the low level hardware */
+ HAL_MspInit();
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief This function de-Initializes common part of the HAL and stops the source of time base.
+ * @note This function is optional.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DeInit(void)
+{
+ /* Reset of all peripherals */
+ __HAL_RCC_APB1_FORCE_RESET();
+ __HAL_RCC_APB1_RELEASE_RESET();
+
+ __HAL_RCC_APB2_FORCE_RESET();
+ __HAL_RCC_APB2_RELEASE_RESET();
+
+ __HAL_RCC_APB3_FORCE_RESET();
+ __HAL_RCC_APB3_RELEASE_RESET();
+
+ __HAL_RCC_AHB1_FORCE_RESET();
+ __HAL_RCC_AHB1_RELEASE_RESET();
+
+ __HAL_RCC_AHB2_FORCE_RESET();
+ __HAL_RCC_AHB2_RELEASE_RESET();
+
+ __HAL_RCC_AHB3_FORCE_RESET();
+ __HAL_RCC_AHB3_RELEASE_RESET();
+
+ /* De-Init the low level hardware */
+ HAL_MspDeInit();
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the MSP.
+ * @retval None
+ */
+__weak void HAL_MspInit(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the MSP.
+ * @retval None
+ */
+__weak void HAL_MspDeInit(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function configures the source of the time base:
+ * The time source is configured to have 1ms time base with a dedicated
+ * Tick interrupt priority.
+ * @note This function is called automatically at the beginning of program after
+ * reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig().
+ * @note In the default implementation, SysTick timer is the source of time base.
+ * It is used to generate interrupts at regular time intervals.
+ * Care must be taken if HAL_Delay() is called from a peripheral ISR process,
+ * The SysTick interrupt must have higher priority (numerically lower)
+ * than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
+ * The function is declared as __weak to be overwritten in case of other
+ * implementation in user file.
+ * @param TickPriority Tick interrupt priority.
+ * @retval HAL status
+ */
+__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if ((uint32_t)uwTickFreq != 0U)
+ {
+ /*Configure the SysTick to have interrupt in 1ms time basis*/
+ if (HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / (1000U / (uint32_t)uwTickFreq)) == 0U)
+ {
+ /* Configure the SysTick IRQ priority */
+ if (TickPriority < (1UL << __NVIC_PRIO_BITS))
+ {
+ HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
+ uwTickPrio = TickPriority;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup HAL_Exported_Functions_Group2
+ * @brief HAL Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Provide a tick value in millisecond
+ (+) Provide a blocking delay in millisecond
+ (+) Suspend the time base source interrupt
+ (+) Resume the time base source interrupt
+ (+) Get the HAL API driver version
+ (+) Get the device revision identifier
+ (+) Get the device identifier
+ (+) Get the unique device identifier
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function is called to increment a global variable "uwTick"
+ * used as application time base.
+ * @note In the default implementation, this variable is incremented each 1ms
+ * in SysTick ISR.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_IncTick(void)
+{
+ uwTick += (uint32_t)uwTickFreq;
+}
+
+/**
+ * @brief Provides a tick value in millisecond.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval tick value
+ */
+__weak uint32_t HAL_GetTick(void)
+{
+ return uwTick;
+}
+
+/**
+ * @brief This function returns a tick priority.
+ * @retval tick priority
+ */
+uint32_t HAL_GetTickPrio(void)
+{
+ return uwTickPrio;
+}
+
+/**
+ * @brief Set new tick Freq.
+ * @retval Status
+ */
+HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_TickFreqTypeDef prevTickFreq;
+
+ assert_param(IS_TICKFREQ(Freq));
+
+ if (uwTickFreq != Freq)
+ {
+ /* Back up uwTickFreq frequency */
+ prevTickFreq = uwTickFreq;
+
+ /* Update uwTickFreq global variable used by HAL_InitTick() */
+ uwTickFreq = Freq;
+
+ /* Apply the new tick Freq */
+ status = HAL_InitTick(uwTickPrio);
+
+ if (status != HAL_OK)
+ {
+ /* Restore previous tick frequency */
+ uwTickFreq = prevTickFreq;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Return tick frequency.
+ * @retval Tick frequency.
+ * Value of @ref HAL_TickFreqTypeDef.
+ */
+HAL_TickFreqTypeDef HAL_GetTickFreq(void)
+{
+ return uwTickFreq;
+}
+
+/**
+ * @brief This function provides minimum delay (in milliseconds) based
+ * on variable incremented.
+ * @note In the default implementation , SysTick timer is the source of time base.
+ * It is used to generate interrupts at regular time intervals where uwTick
+ * is incremented.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @param Delay specifies the delay time length, in milliseconds.
+ * @retval None
+ */
+__weak void HAL_Delay(uint32_t Delay)
+{
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t wait = Delay;
+
+ /* Add a freq to guarantee minimum wait */
+ if (wait < HAL_MAX_DELAY)
+ {
+ wait += (uint32_t)(uwTickFreq);
+ }
+
+ while ((HAL_GetTick() - tickstart) < wait)
+ {
+ }
+}
+
+
+/**
+ * @brief Suspend Tick increment.
+ * @note In the default implementation , SysTick timer is the source of time base. It is
+ * used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
+ * is called, the SysTick interrupt will be disabled and so Tick increment
+ * is suspended.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_SuspendTick(void)
+{
+ /* Disable SysTick Interrupt */
+ CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
+}
+
+/**
+ * @brief Resume Tick increment.
+ * @note In the default implementation , SysTick timer is the source of time base. It is
+ * used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
+ * is called, the SysTick interrupt will be enabled and so Tick increment
+ * is resumed.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_ResumeTick(void)
+{
+ /* Enable SysTick Interrupt */
+ SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
+}
+
+/**
+ * @brief Returns the HAL revision
+ * @retval version : 0xXYZR (8bits for each decimal, R for RC)
+ */
+uint32_t HAL_GetHalVersion(void)
+{
+ return __STM32WBxx_HAL_VERSION;
+}
+
+/**
+ * @brief Returns the device revision identifier.
+ * @retval Device revision identifier
+ */
+uint32_t HAL_GetREVID(void)
+{
+ return (LL_DBGMCU_GetRevisionID());
+}
+
+/**
+ * @brief Returns the device identifier.
+ * @retval Device identifier
+ */
+uint32_t HAL_GetDEVID(void)
+{
+ return (LL_DBGMCU_GetDeviceID());
+}
+
+/**
+ * @brief Return the first word of the unique device identifier (UID based on 96 bits)
+ * @retval Device identifier
+ */
+uint32_t HAL_GetUIDw0(void)
+{
+ return (READ_REG(*((uint32_t *)UID_BASE)));
+}
+
+/**
+ * @brief Return the second word of the unique device identifier (UID based on 96 bits)
+ * @retval Device identifier
+ */
+uint32_t HAL_GetUIDw1(void)
+{
+ return (READ_REG(*((uint32_t *)(UID_BASE + 4U))));
+}
+
+/**
+ * @brief Return the third word of the unique device identifier (UID based on 96 bits)
+ * @retval Device identifier
+ */
+uint32_t HAL_GetUIDw2(void)
+{
+ return (READ_REG(*((uint32_t *)(UID_BASE + 8U))));
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup HAL_Exported_Functions_Group3
+ * @brief HAL Debug functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL Debug functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Enable/Disable Debug module during SLEEP mode
+ (+) Enable/Disable Debug module during STOP mode
+ (+) Enable/Disable Debug module during STANDBY mode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the Debug Module during SLEEP mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGSleepMode(void)
+{
+ LL_DBGMCU_EnableDBGSleepMode();
+}
+
+/**
+ * @brief Disable the Debug Module during SLEEP mode
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGSleepMode(void)
+{
+ LL_DBGMCU_DisableDBGSleepMode();
+}
+
+/**
+ * @brief Enable the Debug Module during STOP mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStopMode(void)
+{
+ LL_DBGMCU_EnableDBGStopMode();
+}
+
+/**
+ * @brief Disable the Debug Module during STOP mode
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGStopMode(void)
+{
+ LL_DBGMCU_DisableDBGStopMode();
+}
+
+/**
+ * @brief Enable the Debug Module during STANDBY mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStandbyMode(void)
+{
+ LL_DBGMCU_EnableDBGStandbyMode();
+}
+
+/**
+ * @brief Disable the Debug Module during STANDBY mode
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGStandbyMode(void)
+{
+ LL_DBGMCU_DisableDBGStandbyMode();
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_Exported_Functions_Group4 HAL System Configuration functions
+ * @brief HAL System Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL system configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start a hardware SRAM2 erase operation
+ (+) Disable CPU2 SRAM fetch (execution)
+ (+) Configure the Voltage reference buffer
+ (+) Enable/Disable the Voltage reference buffer
+ (+) Enable/Disable the I/O analog switch voltage booster
+ (+) Enable/Disable the access for security IP (AES1, AES2, PKA, RNG)
+ (+) Enable/Disable the access for security IP (AES2, PKA, RNG)
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start a hardware SRAM2 erase operation.
+ * @note As long as SRAM2 is not erased the SRAM2ER bit will be set.
+ * This bit is automatically reset at the end of the SRAM2 erase operation.
+ * @retval None
+ */
+void HAL_SYSCFG_SRAM2Erase(void)
+{
+ /* unlock the write protection of the SRAM2ER bit */
+ __HAL_SYSCFG_SRAM2_WRP_UNLOCK();
+ /* Starts a hardware SRAM2 erase operation*/
+ __HAL_SYSCFG_SRAM2_ERASE();
+}
+
+/**
+ * @brief Disable CPU2 SRAM fetch (execution) (This bit can be set by Firmware
+ * and will only be reset by a Hardware reset, including a reset after Standby.)
+ * @note Firmware writing 0 has no effect.
+ * @retval None
+ */
+void HAL_SYSCFG_DisableSRAMFetch(void)
+{
+ LL_SYSCFG_DisableSRAMFetch();
+}
+
+/**
+ * @brief Check if CPU2 SRAM fetch is enabled
+ * @retval State of bit (1 or 0).
+ */
+uint32_t HAL_SYSCFG_IsEnabledSRAMFetch(void)
+{
+ return (LL_SYSCFG_IsEnabledSRAMFetch());
+}
+
+#if defined(VREFBUF)
+/**
+ * @brief Configure the internal voltage reference buffer voltage scale.
+ * @param VoltageScaling specifies the output voltage to achieve
+ * This parameter can be one of the following values:
+ * @arg @ref SYSCFG_VREFBUF_VOLTAGE_SCALE0 : VREF_OUT1 around 2.048 V.
+ * This requires VDDA equal to or higher than 2.4 V.
+ * @arg @ref SYSCFG_VREFBUF_VOLTAGE_SCALE1 : VREF_OUT1 around 2.5 V.
+ * This requires VDDA equal to or higher than 2.8 V.
+ * @note Retrieve the TrimmingValue from factory located at
+ * VREFBUF_SC0_CAL_ADDR or VREFBUF_SC1_CAL_ADDR addresses.
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
+{
+ uint32_t TrimmingValue;
+
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(VoltageScaling));
+
+ LL_VREFBUF_SetVoltageScaling(VoltageScaling);
+
+ /* Restrieve Calibration data and store them into trimming field */
+ if (VoltageScaling == SYSCFG_VREFBUF_VOLTAGE_SCALE0)
+ {
+ TrimmingValue = ((uint32_t) * VREFBUF_SC0_CAL_ADDR) & 0x3FU;
+ }
+ else
+ {
+ TrimmingValue = ((uint32_t) * VREFBUF_SC1_CAL_ADDR) & 0x3FU;
+ }
+ assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue));
+
+ HAL_SYSCFG_VREFBUF_TrimmingConfig(TrimmingValue);
+}
+
+/**
+ * @brief Configure the internal voltage reference buffer high impedance mode.
+ * @param Mode specifies the high impedance mode
+ * This parameter can be one of the following values:
+ * @arg @ref SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE : VREF+ pin is internally connect to VREFINT output.
+ * @arg @ref SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE : VREF+ pin is high impedance.
+ * @retval HAL_OK/HAL_TIMEOUT
+ */
+void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode)
+{
+
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(Mode));
+
+ MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_HIZ, Mode);
+}
+
+/**
+ * @brief Tune the Internal Voltage Reference buffer (VREFBUF).
+ * @note Each VrefBuf voltage scale is calibrated in production for each device,
+ * data stored in flash memory.
+ * Function @ref HAL_SYSCFG_VREFBUF_VoltageScalingConfig retrieves and
+ * applies this calibration data as trimming value at each scale change.
+ * Therefore, optionally, function @ref HAL_SYSCFG_VREFBUF_TrimmingConfig
+ * can be used in a second time to fine tune the trimming.
+ * @param TrimmingValue specifies trimming code for VREFBUF calibration
+ * This parameter can be a number between Min_Data = 0x00 and Max_Data = 0x3F
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue));
+
+ LL_VREFBUF_SetTrimming(TrimmingValue);
+
+}
+
+/**
+ * @brief Enable the Internal Voltage Reference buffer (VREFBUF).
+ * @retval HAL_OK/HAL_TIMEOUT
+ */
+HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void)
+{
+ uint32_t tickstart;
+
+ LL_VREFBUF_Enable();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait for VRR bit */
+ while (READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > VREFBUF_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Internal Voltage Reference buffer (VREFBUF).
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_DisableVREFBUF(void)
+{
+ LL_VREFBUF_Disable();
+}
+#endif /* VREFBUF */
+
+/**
+ * @brief Enable the I/O analog switch voltage booster
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_EnableIOBooster(void)
+{
+ LL_SYSCFG_EnableAnalogBooster();
+}
+
+/**
+ * @brief Disable the I/O analog switch voltage booster
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_DisableIOBooster(void)
+{
+ LL_SYSCFG_DisableAnalogBooster();
+}
+
+#if defined(SYSCFG_CFGR1_ANASWVDD)
+/**
+ * @brief Enable the I/O analog switch supplied by VDD
+ * @note To be used when I/O analog switch voltage booster is not enabled
+ * @retval None
+ */
+void HAL_SYSCFG_EnableIOVdd(void)
+{
+ LL_SYSCFG_EnableAnalogGpioSwitch();
+}
+
+/**
+ * @brief Disable the I/O analog switch supplied by VDD
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_DisableIOVdd(void)
+{
+ LL_SYSCFG_DisableAnalogGpioSwitch();
+}
+#endif /* SYSCFG_CFGR1_ANASWVDD */
+
+/**
+ * @brief Enable the access for security IP
+ * @note When the system is secure (ESE = 1), this register provides write access security and can
+ * only be written by the CPU2. A write access from the CPU1 will be ignored and a bus error
+ * is generated.
+ * @param SecurityAccess This parameter can be a combination of the following values:
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_AES1
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_AES2
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_PKA
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_RNG
+ * @retval None
+ */
+void HAL_SYSCFG_EnableSecurityAccess(uint32_t SecurityAccess)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_SECURITY_ACCESS(SecurityAccess));
+
+ LL_SYSCFG_EnableSecurityAccess(SecurityAccess);
+}
+
+/**
+ * @brief Disable the access for security IP
+ * @note When the system is secure (ESE = 1), this register provides write access security and can
+ * only be written by the CPU2. A write access from the CPU1 will be ignored and a bus error
+ * is generated.
+ * @param SecurityAccess This parameter can be a combination of the following values:
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_AES1
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_AES2
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_PKA
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_RNG
+ * @retval None
+ */
+void HAL_SYSCFG_DisableSecurityAccess(uint32_t SecurityAccess)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_SECURITY_ACCESS(SecurityAccess));
+
+ LL_SYSCFG_DisableSecurityAccess(SecurityAccess);
+}
+
+/**
+ * @brief Indicate if access for security IP is enabled
+ * @param SecurityAccess This parameter can be one of the following values:
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_AES1
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_AES2
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_PKA
+ * @arg @ref HAL_SYSCFG_SECURE_ACCESS_RNG
+ * @retval State of bit (1 or 0).
+ */
+uint32_t HAL_SYSCFG_IsEnabledSecurityAccess(uint32_t SecurityAccess)
+{
+ return (LL_SYSCFG_IsEnabledSecurityAccess(SecurityAccess));
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c
new file mode 100644
index 0000000..5c34a39
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c
@@ -0,0 +1,505 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_cortex.c
+ * @author MCD Application Team
+ * @brief CORTEX HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the CORTEX:
+ * + Initialization and Configuration functions
+ * + Peripheral Control functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ *** How to configure Interrupts using CORTEX HAL driver ***
+ ===========================================================
+ [..]
+ This section provides functions allowing to configure the NVIC interrupts (IRQ).
+ The Cortex M0+ exceptions are managed by CMSIS functions.
+ (#) Enable and Configure the priority of the selected IRQ Channels.
+ The priority can be 0..3.
+
+ -@- Lower priority values gives higher priority.
+ -@- Priority Order:
+ (#@) Lowest priority.
+ (#@) Lowest hardware priority (IRQn position).
+
+ (#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority()
+
+ (#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ()
+
+ -@- Negative value of IRQn_Type are not allowed.
+
+ *** How to configure Systick using CORTEX HAL driver ***
+ ========================================================
+ [..]
+ Setup SysTick Timer for time base.
+
+ (+) The HAL_SYSTICK_Config() function calls the SysTick_Config() function which
+ is a CMSIS function that:
+ (++) Configures the SysTick Reload register with value passed as function parameter.
+ (++) Configures the SysTick IRQ priority to the lowest value (0x03).
+ (++) Resets the SysTick Counter register.
+ (++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK).
+ (++) Enables the SysTick Interrupt.
+ (++) Starts the SysTick Counter.
+
+ (+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro
+ __HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
+ HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined
+ inside the stm32wbxx_hal_cortex.h file.
+
+ (+) You can change the SysTick IRQ priority by calling the
+ HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function
+ call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function.
+
+ (+) To adjust the SysTick time base, use the following formula:
+
+ Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s)
+ (++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function
+ (++) Reload Value should not exceed 0xFFFFFF
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup CORTEX
+ * @{
+ */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup CORTEX_Exported_Functions
+ * @{
+ */
+
+
+/** @addtogroup CORTEX_Exported_Functions_Group1
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and Configuration functions #####
+ ==============================================================================
+ [..]
+ This section provides the CORTEX HAL driver functions allowing to configure Interrupts
+ SysTick functionalities
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set the priority grouping field (pre-emption priority and subpriority)
+ * using the required unlock sequence.
+ * @param PriorityGroup The priority grouping bits length.
+ * This parameter can be one of the following values:
+ * @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority,
+ * 4 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority,
+ * 3 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
+ * 2 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
+ * 1 bit for subpriority
+ * @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
+ * 0 bit for subpriority
+ * @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
+ * The pending IRQ priority will be managed only by the subpriority.
+ * @retval None
+ */
+void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
+
+ /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
+ NVIC_SetPriorityGrouping(PriorityGroup);
+}
+
+/**
+ * @brief Set the priority of an interrupt.
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @param PreemptPriority The pre-emption priority for the IRQn channel.
+ * This parameter can be a value between 0 and 15
+ * A lower priority value indicates a higher priority
+ * @param SubPriority the subpriority level for the IRQ channel.
+ * This parameter can be a value between 0 and 15
+ * A lower priority value indicates a higher priority.
+ * @retval None
+ */
+void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t prioritygroup;
+
+ /* Check the parameters */
+ assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
+ assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
+
+ prioritygroup = NVIC_GetPriorityGrouping();
+
+ NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
+}
+
+/**
+ * @brief Enable a device specific interrupt in the NVIC interrupt controller.
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Enable interrupt */
+ NVIC_EnableIRQ(IRQn);
+}
+
+/**
+ * @brief Disable a device specific interrupt in the NVIC interrupt controller.
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Disable interrupt */
+ NVIC_DisableIRQ(IRQn);
+}
+
+/**
+ * @brief Initiate a system reset request to reset the MCU.
+ * @retval None
+ */
+void HAL_NVIC_SystemReset(void)
+{
+ /* System Reset */
+ NVIC_SystemReset();
+}
+
+/**
+ * @brief Initialize the System Timer with interrupt enabled and start the System Tick Timer (SysTick):
+ * Counter is in free running mode to generate periodic interrupts.
+ * @param TicksNumb Specifies the ticks Number of ticks between two interrupts.
+ * @retval status: - 0 Function succeeded.
+ * - 1 Function failed.
+ */
+uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
+{
+ return SysTick_Config(TicksNumb);
+}
+/**
+ * @}
+ */
+
+/** @addtogroup CORTEX_Exported_Functions_Group2
+ * @brief Cortex control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the CORTEX
+ (NVIC, SYSTICK, MPU) functionalities.
+
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Get the priority grouping field from the NVIC Interrupt Controller.
+ * @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field)
+ */
+uint32_t HAL_NVIC_GetPriorityGrouping(void)
+{
+ /* Get the PRIGROUP[10:8] field value */
+ return NVIC_GetPriorityGrouping();
+}
+
+/**
+ * @brief Get the priority of an interrupt.
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @param PriorityGroup the priority grouping bits length.
+ * This parameter can be one of the following values:
+ * @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority,
+ * 4 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority,
+ * 3 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
+ * 2 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
+ * 1 bit for subpriority
+ * @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
+ * 0 bit for subpriority
+ * @param pPreemptPriority Pointer on the Preemptive priority value (starting from 0).
+ * @param pSubPriority Pointer on the Subpriority value (starting from 0).
+ * @retval None
+ */
+void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
+ /* Get priority for Cortex-M system or device specific interrupts */
+ NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority);
+}
+
+/**
+ * @brief Set Pending bit of an external interrupt.
+ * @param IRQn External interrupt number
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Set interrupt pending */
+ NVIC_SetPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Get Pending Interrupt (read the pending register in the NVIC
+ * and return the pending bit for the specified interrupt).
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @retval status: - 0 Interrupt status is not pending.
+ * - 1 Interrupt status is pending.
+ */
+uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Return 1 if pending else 0 */
+ return NVIC_GetPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Clear the pending bit of an external interrupt.
+ * @param IRQn External interrupt number.
+ * This parameter can be an enumerator of IRQn_Type enumeration
+ * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbxxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Clear pending interrupt */
+ NVIC_ClearPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Configure the SysTick clock source.
+ * @param CLKSource specifies the SysTick clock source.
+ * This parameter can be one of the following values:
+ * @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source.
+ * @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source.
+ * @retval None
+ */
+void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));
+ if (CLKSource == SYSTICK_CLKSOURCE_HCLK)
+ {
+ SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
+ }
+ else
+ {
+ SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK;
+ }
+}
+
+/**
+ * @brief Handle SYSTICK interrupt request.
+ * @retval None
+ */
+void HAL_SYSTICK_IRQHandler(void)
+{
+ HAL_SYSTICK_Callback();
+}
+
+/**
+ * @brief SYSTICK callback.
+ * @retval None
+ */
+__weak void HAL_SYSTICK_Callback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SYSTICK_Callback could be implemented in the user file
+ */
+}
+
+#if (__MPU_PRESENT == 1U)
+/**
+ * @brief Disables the MPU
+ * @retval None
+ */
+void HAL_MPU_Disable(void)
+{
+ /* Make sure outstanding transfers are done */
+ __DMB();
+
+ /* Disable fault exceptions */
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+
+ /* Disable the MPU and clear the control register*/
+ MPU->CTRL = 0U;
+}
+
+/**
+ * @brief Enable the MPU.
+ * @param MPU_Control: Specifies the control mode of the MPU during hard fault,
+ * NMI, FAULTMASK and privileged access to the default memory
+ * This parameter can be one of the following values:
+ * @arg MPU_HFNMI_PRIVDEF_NONE
+ * @arg MPU_HARDFAULT_NMI
+ * @arg MPU_PRIVILEGED_DEFAULT
+ * @arg MPU_HFNMI_PRIVDEF
+ * @retval None
+ */
+void HAL_MPU_Enable(uint32_t MPU_Control)
+{
+ /* Enable the MPU */
+ MPU->CTRL = (MPU_Control | MPU_CTRL_ENABLE_Msk);
+
+ /* Enable fault exceptions */
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+
+ /* Ensure MPU setting take effects */
+ __DSB();
+ __ISB();
+}
+
+/**
+ * @brief Enable the MPU Region.
+ * @retval None
+ */
+void HAL_MPU_EnableRegion(uint32_t RegionNumber)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(RegionNumber));
+
+ /* Set the Region number */
+ MPU->RNR = RegionNumber;
+
+ /* Enable the Region */
+ SET_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
+}
+
+/**
+ * @brief Disable the MPU Region.
+ * @retval None
+ */
+void HAL_MPU_DisableRegion(uint32_t RegionNumber)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(RegionNumber));
+
+ /* Set the Region number */
+ MPU->RNR = RegionNumber;
+
+ /* Disable the Region */
+ CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
+}
+
+/**
+ * @brief Initialize and configure the Region and the memory to be protected.
+ * @param MPU_Init Pointer to a MPU_Region_InitTypeDef structure that contains
+ * the initialization and configuration information.
+ * @retval None
+ */
+void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));
+ assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));
+ assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));
+ assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));
+ assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));
+ assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));
+ assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));
+ assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));
+ assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));
+ assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));
+
+ /* Set the Region number */
+ MPU->RNR = MPU_Init->Number;
+
+ /* Disable the Region */
+ CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
+
+ /* Apply configuration */
+ MPU->RBAR = MPU_Init->BaseAddress;
+ MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) |
+ ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) |
+ ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) |
+ ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) |
+ ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) |
+ ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) |
+ ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) |
+ ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) |
+ ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos);
+}
+#endif /* __MPU_PRESENT */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma.c
new file mode 100644
index 0000000..316e71f
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma.c
@@ -0,0 +1,1120 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_dma.c
+ * @author MCD Application Team
+ * @brief DMA HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Direct Memory Access (DMA) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and errors functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Enable and configure the peripheral to be connected to the DMA Channel
+ (except for internal SRAM / FLASH memories: no initialization is
+ necessary). Please refer to the Reference manual for connection between peripherals
+ and DMA requests.
+
+ (#) For a given Channel, program the required configuration through the following parameters:
+ Channel request, Transfer Direction, Source and Destination data formats,
+ Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
+ using HAL_DMA_Init() function.
+
+ Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX
+ thanks to:
+ (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ;
+ (##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE();
+
+ (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
+ detection.
+
+ (#) Use HAL_DMA_Abort() function to abort the current transfer
+
+ -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
+ address and destination address and the Length of data to be transferred
+ (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
+ case a fixed Timeout can be configured by User depending from his application.
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
+ (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
+ (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
+ Source address and destination address and the Length of data to be transferred.
+ In this case the DMA interrupt is configured
+ (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
+ (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
+ add his own function to register callbacks with HAL_DMA_RegisterCallback().
+
+ *** DMA HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of macros in DMA HAL driver.
+
+ (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
+ (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
+ (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
+ (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
+ (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
+ (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
+ (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not.
+
+ [..]
+ (@) You can refer to the DMA HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMA DMA
+ * @brief DMA HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup DMA_Private_Functions DMA Private Functions
+ * @{
+ */
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
+static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
+static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
+
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup DMA_Exported_Functions DMA Exported Functions
+ * @{
+ */
+
+/** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to initialize the DMA Channel source
+ and destination addresses, incrementation and data sizes, transfer direction,
+ circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
+ [..]
+ The HAL_DMA_Init() function follows the DMA configuration procedures as described in
+ reference manual.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DMA according to the specified
+ * parameters in the DMA_InitTypeDef and initialize the associated handle.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tmp;
+
+ /* Check the DMA handle allocation */
+ if (hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+ assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
+ assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
+ assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
+ assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
+ assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
+ assert_param(IS_DMA_MODE(hdma->Init.Mode));
+ assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
+
+ assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));
+
+#if defined(DMA2)
+ /* Compute the channel index */
+ if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
+ {
+ /* DMA1 */
+ hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
+ hdma->DmaBaseAddress = DMA1;
+ }
+ else
+ {
+ /* DMA2 */
+ hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
+ hdma->DmaBaseAddress = DMA2;
+ }
+#else
+ /* DMA1 */
+ hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
+ hdma->DmaBaseAddress = DMA1;
+#endif /* DMA2 */
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Get the CR register value */
+ tmp = hdma->Instance->CCR;
+
+ /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
+ tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE |
+ DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC |
+ DMA_CCR_DIR | DMA_CCR_MEM2MEM));
+
+ /* Prepare the DMA Channel configuration */
+ tmp |= hdma->Init.Direction |
+ hdma->Init.PeriphInc | hdma->Init.MemInc |
+ hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
+ hdma->Init.Mode | hdma->Init.Priority;
+
+ /* Write to DMA Channel CR register */
+ hdma->Instance->CCR = tmp;
+
+ /* Initialize parameters for DMAMUX channel :
+ DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
+ */
+ DMA_CalcDMAMUXChannelBaseAndMask(hdma);
+
+ if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
+ {
+ /* if memory to memory force the request to 0*/
+ hdma->Init.Request = DMA_REQUEST_MEM2MEM;
+ }
+
+ /* Set peripheral request to DMAMUX channel */
+ hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if (((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
+ {
+ /* Initialize parameters for DMAMUX request generator :
+ DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
+ */
+ DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
+
+ /* Reset the DMAMUX request generator register*/
+ hdma->DMAmuxRequestGen->RGCR = 0U;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ else
+ {
+ hdma->DMAmuxRequestGen = 0U;
+ hdma->DMAmuxRequestGenStatus = 0U;
+ hdma->DMAmuxRequestGenStatusMask = 0U;
+ }
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the DMA state*/
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Allocate lock resource and initialize it */
+ hdma->Lock = HAL_UNLOCKED;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the DMA peripheral.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
+{
+
+ /* Check the DMA handle allocation */
+ if (NULL == hdma)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ /* Disable the selected DMA Channelx */
+ __HAL_DMA_DISABLE(hdma);
+
+#if defined(DMA2)
+ /* Compute the channel index */
+ if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
+ {
+ /* DMA1 */
+ hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
+ hdma->DmaBaseAddress = DMA1;
+ }
+ else
+ {
+ /* DMA2 */
+ hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
+ hdma->DmaBaseAddress = DMA2;
+ }
+#else
+ /* DMA1 */
+ hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
+ hdma->DmaBaseAddress = DMA1;
+#endif /* DMA2 */
+
+ /* Reset DMA Channel control register */
+ hdma->Instance->CCR = 0U;
+
+ /* Clear all flags */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Initialize parameters for DMAMUX channel :
+ DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
+
+ DMA_CalcDMAMUXChannelBaseAndMask(hdma);
+
+ /* Reset the DMAMUX channel that corresponds to the DMA channel */
+ hdma->DMAmuxChannel->CCR = 0U;
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ /* Reset Request generator parameters if any */
+ if (((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
+ {
+ /* Initialize parameters for DMAMUX request generator :
+ DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
+ */
+ DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
+
+ /* Reset the DMAMUX request generator register*/
+ hdma->DMAmuxRequestGen->RGCR = 0U;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+
+ hdma->DMAmuxRequestGen = 0U;
+ hdma->DMAmuxRequestGenStatus = 0U;
+ hdma->DMAmuxRequestGenStatusMask = 0U;
+
+ /* Clean callbacks */
+ hdma->XferCpltCallback = NULL;
+ hdma->XferHalfCpltCallback = NULL;
+ hdma->XferErrorCallback = NULL;
+ hdma->XferAbortCallback = NULL;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the DMA state */
+ hdma->State = HAL_DMA_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
+ * @brief Input and Output operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the source, destination address and data length and Start DMA transfer
+ (+) Configure the source, destination address and data length and
+ Start DMA transfer with interrupt
+ (+) Abort DMA transfer
+ (+) Poll for transfer complete
+ (+) Handle DMA interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the DMA Transfer.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @param SrcAddress The source memory Buffer address
+ * @param DstAddress The destination memory Buffer address
+ * @param DataLength The length of data to be transferred from source to destination
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if (HAL_DMA_STATE_READY == hdma->State)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Disable the peripheral */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Configure the source, destination address and the data length & clear flags*/
+ DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ /* Enable the Peripheral */
+ __HAL_DMA_ENABLE(hdma);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ status = HAL_BUSY;
+ }
+ return status;
+}
+
+/**
+ * @brief Start the DMA Transfer with interrupt enabled.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @param SrcAddress The source memory Buffer address
+ * @param DstAddress The destination memory Buffer address
+ * @param DataLength The length of data to be transferred from source to destination
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress,
+ uint32_t DataLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if (HAL_DMA_STATE_READY == hdma->State)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Disable the peripheral */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Configure the source, destination address and the data length & clear flags*/
+ DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ /* Enable the transfer complete interrupt */
+ /* Enable the transfer Error interrupt */
+ if (NULL != hdma->XferHalfCpltCallback)
+ {
+ /* Enable the Half transfer complete interrupt as well */
+ __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
+ }
+ else
+ {
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
+ __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
+ }
+
+ /* Check if DMAMUX Synchronization is enabled*/
+ if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
+ {
+ /* Enable DMAMUX sync overrun IT*/
+ hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
+ }
+
+ if (hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
+ /* enable the request gen overrun IT*/
+ hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
+ }
+
+ /* Enable the Peripheral */
+ __HAL_DMA_ENABLE(hdma);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Remain BUSY */
+ status = HAL_BUSY;
+ }
+ return status;
+}
+
+/**
+ * @brief Abort the DMA Transfer.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
+{
+
+ /* Check the DMA peripheral handle */
+ if (NULL == hdma)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the DMA peripheral state */
+ if (hdma->State != HAL_DMA_STATE_BUSY)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Disable DMA IT */
+ __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
+
+ /* disable the DMAMUX sync overrun IT*/
+ hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
+
+ /* Disable the channel */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Clear all flags */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if (hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
+ /* disable the request gen overrun IT*/
+ hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Aborts the DMA Transfer in Interrupt mode.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_DMA_STATE_BUSY != hdma->State)
+ {
+ /* no transfer ongoing */
+ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
+
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Disable DMA IT */
+ __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
+
+ /* Disable the channel */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* disable the DMAMUX sync overrun IT*/
+ hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
+
+ /* Clear all flags */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if (hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
+ /* disable the request gen overrun IT*/
+ hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Call User Abort callback */
+ if (hdma->XferAbortCallback != NULL)
+ {
+ hdma->XferAbortCallback(hdma);
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Polling for transfer complete.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @param CompleteLevel Specifies the DMA level complete.
+ * @param Timeout Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel,
+ uint32_t Timeout)
+{
+ uint32_t temp;
+ uint32_t tickstart;
+
+ if (HAL_DMA_STATE_BUSY != hdma->State)
+ {
+ /* no transfer ongoing */
+ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
+ __HAL_UNLOCK(hdma);
+ return HAL_ERROR;
+ }
+
+ /* Polling mode not supported in circular mode */
+ if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
+ return HAL_ERROR;
+ }
+
+ /* Get the level transfer complete flag */
+ if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
+ {
+ /* Transfer Complete flag */
+ temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
+ }
+ else
+ {
+ /* Half Transfer Complete flag */
+ temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU);
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while ((hdma->DmaBaseAddress->ISR & temp) == 0U)
+ {
+ if ((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU))) != 0U)
+ {
+ /* When a DMA transfer error occurs */
+ /* A hardware clear of its EN bits is performed */
+ /* Clear all flags */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TE;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /*Check for DMAMUX Request generator (if used) overrun status */
+ if (hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
+ if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
+ {
+ /* Disable the request gen overrun interrupt */
+ hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
+ }
+ }
+
+ /* Check for DMAMUX Synchronization overrun */
+ if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
+ {
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
+ }
+
+ if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
+ {
+ /* Clear the transfer complete flag */
+ hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* The selected Channelx EN bit is cleared (DMA is disabled and
+ all transfers are complete) */
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+ else
+ {
+ /* Clear the half transfer complete flag */
+ hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU));
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle DMA interrupt request.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval None
+ */
+void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
+{
+ uint32_t flag_it = hdma->DmaBaseAddress->ISR;
+ uint32_t source_it = hdma->Instance->CCR;
+
+ /* Half Transfer Complete Interrupt management ******************************/
+ if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
+ {
+ /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
+ if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
+ {
+ /* Disable the half transfer interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
+ }
+ /* Clear the half transfer complete flag */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU));
+
+ /* DMA peripheral state is not updated in Half Transfer */
+ /* but in Transfer Complete case */
+
+ if (hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Half transfer callback */
+ hdma->XferHalfCpltCallback(hdma);
+ }
+ }
+
+ /* Transfer Complete Interrupt management ***********************************/
+ else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
+ {
+ if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
+ {
+ /* Disable the transfer complete and error interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+ /* Clear the transfer complete flag */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if (hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete callback */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+
+ /* Transfer Error Interrupt management **************************************/
+ else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
+ {
+ /* When a DMA transfer error occurs */
+ /* A hardware clear of its EN bits is performed */
+ /* Disable ALL DMA IT */
+ __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
+
+ /* Clear all flags */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TE;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if (hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ else
+ {
+ /* Nothing To Do */
+ }
+ return;
+}
+
+/**
+ * @brief Register callbacks
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @param CallbackID User Callback identifier
+ * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
+ * @param pCallback Pointer to private callback function which has pointer to
+ * a DMA_HandleTypeDef structure as parameter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if (HAL_DMA_STATE_READY == hdma->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA_XFER_CPLT_CB_ID:
+ hdma->XferCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_HALFCPLT_CB_ID:
+ hdma->XferHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_ERROR_CB_ID:
+ hdma->XferErrorCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_ABORT_CB_ID:
+ hdma->XferAbortCallback = pCallback;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma);
+
+ return status;
+}
+
+/**
+ * @brief UnRegister callbacks
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @param CallbackID User Callback identifier
+ * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if (HAL_DMA_STATE_READY == hdma->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA_XFER_CPLT_CB_ID:
+ hdma->XferCpltCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_HALFCPLT_CB_ID:
+ hdma->XferHalfCpltCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_ERROR_CB_ID:
+ hdma->XferErrorCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_ABORT_CB_ID:
+ hdma->XferAbortCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_ALL_CB_ID:
+ hdma->XferCpltCallback = NULL;
+ hdma->XferHalfCpltCallback = NULL;
+ hdma->XferErrorCallback = NULL;
+ hdma->XferAbortCallback = NULL;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma);
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral State and Errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the DMA state
+ (+) Get error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the DMA handle state.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval HAL state
+ */
+HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
+{
+ /* Return DMA handle state */
+ return hdma->State;
+}
+
+/**
+ * @brief Return the DMA error code.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval DMA Error Code
+ */
+uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
+{
+ return hdma->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup DMA_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Sets the DMA Transfer parameter.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @param SrcAddress The source memory Buffer address
+ * @param DstAddress The destination memory Buffer address
+ * @param DataLength The length of data to be transferred from source to destination
+ * @retval HAL status
+ */
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
+{
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if (hdma->DMAmuxRequestGen != 0U)
+ {
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+
+ /* Clear all flags */
+ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
+
+ /* Configure DMA Channel data length */
+ hdma->Instance->CNDTR = DataLength;
+
+ /* Memory to Peripheral */
+ if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
+ {
+ /* Configure DMA Channel destination address */
+ hdma->Instance->CPAR = DstAddress;
+
+ /* Configure DMA Channel source address */
+ hdma->Instance->CMAR = SrcAddress;
+ }
+ /* Peripheral to Memory */
+ else
+ {
+ /* Configure DMA Channel source address */
+ hdma->Instance->CPAR = SrcAddress;
+
+ /* Configure DMA Channel destination address */
+ hdma->Instance->CMAR = DstAddress;
+ }
+}
+
+/**
+ * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on channel number
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval None
+ */
+static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
+{
+ uint32_t channel_number;
+
+ /* check if instance is not outside the DMA channel range */
+#if defined(DMA2)
+ if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1)
+ {
+ /* DMA1 */
+ hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
+ }
+ else
+ {
+ /* DMA2 */
+ hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U));
+ }
+#else
+ /* DMA1 */
+ hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
+#endif /* DMA2 */
+ channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
+ hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
+
+ /* Initialize the field DMAmuxChannelStatusMask with the corresponding index of the DMAMUX channel selected for the current ChannelIndex */
+ hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1FU);
+}
+
+/**
+ * @brief Updates the DMA handle with the DMAMUX request generator params
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ * @retval None
+ */
+
+static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
+{
+ uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
+
+ /* DMA Channels are connected to DMAMUX1 request generator blocks*/
+ hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
+
+ hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
+
+ /* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/
+ hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma_ex.c
new file mode 100644
index 0000000..239665c
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma_ex.c
@@ -0,0 +1,295 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_dma_ex.c
+ * @author MCD Application Team
+ * @brief DMA Extension HAL module driver
+ * This file provides firmware functions to manage the following
+ * functionalities of the DMA Extension peripheral:
+ * + Extended features functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The DMA Extension HAL driver can be used as follows:
+
+ (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
+ (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
+ Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
+ to respectively enable/disable the request generator.
+
+ (+) To handle the DMAMUX Interrupts, the function HAL_DMAEx_MUX_IRQHandler should be called from
+ the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler.
+ As only one interrupt line is available for all DMAMUX channels and request generators , HAL_DMAEx_MUX_IRQHandler should be
+ called with, as parameter, the appropriate DMA handle as many as used DMAs in the user project
+ (exception done if a given DMA is not using the DMAMUX SYNC block neither a request generator)
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMAEx DMAEx
+ * @brief DMA Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private Constants ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+
+/** @defgroup DMAEx_Exported_Functions DMAEx Exported Functions
+ * @{
+ */
+
+/** @defgroup DMAEx_Exported_Functions_Group1 DMAEx Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+ (+) Configure the DMAMUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
+ (+) Configure the DMAMUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
+ Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
+ to respectively enable/disable the request generator.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the DMAMUX synchronization parameters for a given DMA channel (instance).
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA channel.
+ * @param pSyncConfig Pointer to HAL_DMA_MuxSyncConfigTypeDef : contains the DMAMUX synchronization parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ assert_param(IS_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
+ assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig-> SyncPolarity));
+ assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable));
+ assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable));
+ assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber));
+
+ /*Check if the DMA state is ready */
+ if (hdma->State == HAL_DMA_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hdma);
+
+ /* Set the new synchronization parameters (and keep the request ID filled during the Init)*/
+ MODIFY_REG(hdma->DMAmuxChannel->CCR, \
+ (DMAMUX_CxCR_SYNC_ID | DMAMUX_CxCR_NBREQ | DMAMUX_CxCR_SPOL | DMAMUX_CxCR_SE | DMAMUX_CxCR_EGE), \
+ (pSyncConfig->SyncSignalID | \
+ ((pSyncConfig->RequestNumber - 1U) << DMAMUX_CxCR_NBREQ_Pos) | \
+ pSyncConfig->SyncPolarity | \
+ ((uint32_t)pSyncConfig->SyncEnable << DMAMUX_CxCR_SE_Pos) | \
+ ((uint32_t)pSyncConfig->EventEnable << DMAMUX_CxCR_EGE_Pos)));
+
+ /* Process UnLocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /*DMA State not Ready*/
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the DMAMUX request generator block used by the given DMA channel (instance).
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA channel.
+ * @param pRequestGeneratorConfig Pointer to HAL_DMA_MuxRequestGeneratorConfigTypeDef :
+ * contains the request generator parameters.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator(DMA_HandleTypeDef *hdma,
+ HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ assert_param(IS_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
+ assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity));
+ assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber));
+
+ /* check if the DMA state is ready
+ and DMA is using a DMAMUX request generator block
+ */
+ if ((hdma->State == HAL_DMA_STATE_READY) && (hdma->DMAmuxRequestGen != 0U))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hdma);
+
+ /* Set the request generator new parameters*/
+ WRITE_REG(hdma->DMAmuxRequestGen->RGCR, (pRequestGeneratorConfig->SignalID | \
+ pRequestGeneratorConfig->Polarity | \
+ ((pRequestGeneratorConfig->RequestNumber - 1U) << DMAMUX_RGxCR_GNBREQ_Pos)));
+
+ /* Process UnLocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable the DMAMUX request generator block used by the given DMA channel (instance).
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator(DMA_HandleTypeDef *hdma)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ /* check if the DMA state is ready
+ and DMA is using a DMAMUX request generator block
+ */
+ if ((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
+ {
+ /* Enable the request generator*/
+ SET_BIT(hdma->DMAmuxRequestGen->RGCR, DMAMUX_RGxCR_GE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable the DMAMUX request generator block used by the given DMA channel (instance).
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator(DMA_HandleTypeDef *hdma)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ /* check if the DMA state is ready
+ and DMA is using a DMAMUX request generator block
+ */
+ if ((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0))
+ {
+ /* Disable the request generator*/
+ CLEAR_BIT(hdma->DMAmuxRequestGen->RGCR, DMAMUX_RGxCR_GE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Handles DMAMUX interrupt request.
+ * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA channel.
+ * @retval None
+ */
+void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma)
+{
+ /* Check for DMAMUX Synchronization overrun */
+ if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
+ {
+ /* Disable the synchro overrun interrupt */
+ CLEAR_BIT(hdma->DMAmuxChannel->CCR, DMAMUX_CxCR_SOIE);
+
+ /* Clear the DMAMUX synchro overrun flag */
+ WRITE_REG(hdma->DMAmuxChannelStatus->CFR, hdma->DMAmuxChannelStatusMask);
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
+
+ if (hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+
+ if (hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using a DMAMUX request generator block Check for DMAMUX request generator overrun */
+ if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
+ {
+ /* Disable the request gen overrun interrupt */
+ CLEAR_BIT(hdma->DMAmuxRequestGen->RGCR, DMAMUX_RGxCR_OIE);
+
+ /* Clear the DMAMUX request generator overrun flag */
+ WRITE_REG(hdma->DMAmuxRequestGenStatus->RGCFR, hdma->DMAmuxRequestGenStatusMask);
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
+
+ if (hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c
new file mode 100644
index 0000000..ec29590
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c
@@ -0,0 +1,634 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_exti.c
+ * @author MCD Application Team
+ * @brief EXTI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the General Purpose Input/Output (EXTI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### EXTI Peripheral features #####
+ ==============================================================================
+ [..]
+ (+) Each Exti line can be configured within this driver.
+
+ (+) Exti line can be configured in 3 different modes
+ (++) Interrupt
+ (++) Event
+ (++) Both of them
+
+ (+) Configurable Exti lines can be configured with 3 different triggers
+ (++) Rising
+ (++) Falling
+ (++) Both of them
+
+ (+) When set in interrupt mode, configurable Exti lines have one
+ interrupt pending register:
+ (++) Trigger request occurred
+
+ (+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
+ be selected through multiplexer.
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+
+ (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
+ (++) Choose the interrupt line number by setting "Line" member from
+ EXTI_ConfigTypeDef structure.
+ (++) Configure the interrupt and/or event mode using "Mode" member from
+ EXTI_ConfigTypeDef structure.
+ (++) For configurable lines, configure rising and/or falling trigger
+ "Trigger" member from EXTI_ConfigTypeDef structure.
+ (++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
+ member from GPIO_InitTypeDef structure.
+
+ (#) Get current Exti configuration of a dedicated line using
+ HAL_EXTI_GetConfigLine().
+ (++) Provide exiting handle as parameter.
+ (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
+
+ (#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
+ (++) Provide exiting handle as parameter.
+
+ (#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
+ (++) Provide exiting handle as first parameter.
+ (++) Provide which callback will be registered using one value from
+ EXTI_CallbackIDTypeDef.
+ (++) Provide callback function pointer.
+
+ (#) Get interrupt pending bit using HAL_EXTI_GetPending().
+
+ (#) Clear interrupt pending bit using HAL_EXTI_GetPending().
+
+ (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup EXTI
+ * @{
+ */
+/** MISRA C:2012 deviation rule has been granted for following rule:
+ * Rule-18.1_b - Medium: Array `EXTICR' 1st subscript interval [0,7] may be out
+ * of bounds [0,3] in following API :
+ * HAL_EXTI_SetConfigLine
+ * HAL_EXTI_GetConfigLine
+ * HAL_EXTI_ClearConfigLine
+ */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines ------------------------------------------------------------*/
+/** @defgroup EXTI_Private_Constants EXTI Private Constants
+ * @{
+ */
+#define EXTI_MODE_OFFSET 0x04u /* 0x10: offset between CPU IMR/EMR registers */
+#define EXTI_CONFIG_OFFSET 0x08u /* 0x20: offset between CPU Rising/Falling configuration registers */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup EXTI_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup EXTI_Exported_Functions_Group1
+ * @brief Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Configuration functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set configuration of a dedicated Exti line.
+ * @param hexti Exti handle.
+ * @param pExtiConfig Pointer on EXTI configuration to be set.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check null pointer */
+ if ((hexti == NULL) || (pExtiConfig == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(pExtiConfig->Line));
+ assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
+
+ /* Assign line number to handle */
+ hexti->Line = pExtiConfig->Line;
+
+ /* compute line register offset and line mask */
+ offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
+ maskline = (1uL << linepos);
+
+ /* Configure triggers for configurable lines */
+ if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
+ {
+ assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
+
+ /* Configure rising trigger */
+ regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00u)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store rising trigger mode */
+ *regaddr = regval;
+
+ /* Configure falling trigger */
+ regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store falling trigger mode */
+ *regaddr = regval;
+
+ /* Configure gpio port selection in case of gpio exti line */
+ if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
+ {
+ assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
+ assert_param(IS_EXTI_GPIO_PIN(linepos));
+
+ regval = SYSCFG->EXTICR[linepos >> 2u];
+ regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
+ regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
+ SYSCFG->EXTICR[linepos >> 2u] = regval;
+ }
+ }
+
+ /* Configure interrupt mode : read current mode */
+ regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00u)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store interrupt mode */
+ *regaddr = regval;
+
+ /* The event mode cannot be configured if the line does not support it */
+ assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
+
+ /* Configure event mode : read current mode */
+ regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00u)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store event mode */
+ *regaddr = regval;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Get configuration of a dedicated Exti line.
+ * @param hexti Exti handle.
+ * @param pExtiConfig Pointer on structure to store Exti configuration.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check null pointer */
+ if ((hexti == NULL) || (pExtiConfig == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+
+ /* Store handle line number to configuration structure */
+ pExtiConfig->Line = hexti->Line;
+
+ /* compute line register offset and line mask */
+ offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
+ maskline = (1uL << linepos);
+
+ /* 1] Get core mode : interrupt */
+ regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if selected line is enable */
+ if ((regval & maskline) != 0x00u)
+ {
+ pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
+ }
+ else
+ {
+ pExtiConfig->Mode = EXTI_MODE_NONE;
+ }
+
+ /* Get event mode */
+ regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if selected line is enable */
+ if ((regval & maskline) != 0x00u)
+ {
+ pExtiConfig->Mode |= EXTI_MODE_EVENT;
+ }
+
+ /* Get default Trigger and GPIOSel configuration */
+ pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
+ pExtiConfig->GPIOSel = 0x00u;
+
+ /* 2] Get trigger for configurable lines : rising */
+ if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
+ {
+ regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if configuration of selected line is enable */
+ if ((regval & maskline) != 0x00u)
+ {
+ pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
+ }
+
+ /* Get falling configuration */
+ regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if configuration of selected line is enable */
+ if ((regval & maskline) != 0x00u)
+ {
+ pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
+ }
+
+ /* Get Gpio port selection for gpio lines */
+ if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
+ {
+ assert_param(IS_EXTI_GPIO_PIN(linepos));
+
+ regval = SYSCFG->EXTICR[linepos >> 2u];
+ pExtiConfig->GPIOSel = (regval >> (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u))) & SYSCFG_EXTICR1_EXTI0;
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Clear whole configuration of a dedicated Exti line.
+ * @param hexti Exti handle.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check null pointer */
+ if (hexti == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (hexti->Line & EXTI_PIN_MASK);
+ maskline = (1uL << linepos);
+
+ /* 1] Clear interrupt mode */
+ regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ /* 2] Clear event mode */
+ regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ /* 3] Clear triggers in case of configurable lines */
+ if ((hexti->Line & EXTI_CONFIG) != 0x00u)
+ {
+ regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ /* Get Gpio port selection for gpio lines */
+ if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
+ {
+ assert_param(IS_EXTI_GPIO_PIN(linepos));
+
+ regval = SYSCFG->EXTICR[linepos >> 2u];
+ regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
+ SYSCFG->EXTICR[linepos >> 2u] = regval;
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Register callback for a dedicaated Exti line.
+ * @param hexti Exti handle.
+ * @param CallbackID User callback identifier.
+ * This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
+ * @param pPendingCbfn function pointer to be stored as callback.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID,
+ void (*pPendingCbfn)(void))
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ switch (CallbackID)
+ {
+ case HAL_EXTI_COMMON_CB_ID:
+ hexti->PendingCallback = pPendingCbfn;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+
+/**
+ * @brief Store line number as handle private field.
+ * @param hexti Exti handle.
+ * @param ExtiLine Exti line number.
+ * This parameter can be from 0 to @ref EXTI_LINE_NB.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
+{
+ /* Check the parameters */
+ assert_param(IS_EXTI_LINE(ExtiLine));
+
+ /* Check null pointer */
+ if (hexti == NULL)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Store line number as handle private field */
+ hexti->Line = ExtiLine;
+
+ return HAL_OK;
+ }
+}
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup EXTI_Exported_Functions_Group2
+ * @brief EXTI IO functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle EXTI interrupt request.
+ * @param hexti Exti handle.
+ * @retval none.
+ */
+void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
+
+ /* Get pending bit */
+ regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = (*regaddr & maskline);
+
+ if (regval != 0x00u)
+ {
+ /* Clear pending bit */
+ *regaddr = maskline;
+
+ /* Call callback */
+ if (hexti->PendingCallback != NULL)
+ {
+ hexti->PendingCallback();
+ }
+ }
+}
+
+
+/**
+ * @brief Get interrupt pending bit of a dedicated line.
+ * @param hexti Exti handle.
+ * @param Edge Specify which pending edge as to be checked.
+ * This parameter can be one of the following values:
+ * @arg @ref EXTI_TRIGGER_RISING_FALLING
+ * This parameter is kept for compatibility with other series.
+ * @retval 1 if interrupt is pending else 0.
+ */
+uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Edge);
+
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (hexti->Line & EXTI_PIN_MASK);
+ maskline = (1uL << linepos);
+
+ /* Get pending bit */
+ regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
+
+ /* return 1 if bit is set else 0 */
+ regval = ((*regaddr & maskline) >> linepos);
+ return regval;
+}
+
+
+/**
+ * @brief Clear interrupt pending bit of a dedicated line.
+ * @param hexti Exti handle.
+ * @param Edge Specify which pending edge as to be clear.
+ * This parameter can be one of the following values:
+ * @arg @ref EXTI_TRIGGER_RISING_FALLING
+ * This parameter is kept for compatibility with other series.
+ * @retval None.
+ */
+void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Edge);
+
+ __IO uint32_t *regaddr;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
+
+ /* Get pending register address */
+ regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
+
+ /* Clear Pending bit */
+ *regaddr = maskline;
+}
+
+
+/**
+ * @brief Generate a software interrupt for a dedicated line.
+ * @param hexti Exti handle.
+ * @retval None.
+ */
+void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
+
+ regaddr = (&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
+ *regaddr = maskline;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_EXTI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c
new file mode 100644
index 0000000..4f2232a
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c
@@ -0,0 +1,743 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_flash.c
+ * @author MCD Application Team
+ * @brief FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the internal FLASH memory:
+ * + Program operations functions
+ * + Memory Control functions
+ * + Peripheral Errors functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### FLASH peripheral features #####
+ ==============================================================================
+
+ [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
+ to the Flash memory. It implements the erase and program Flash memory operations
+ and the read and write protection mechanisms.
+
+ [..] The Flash memory interface accelerates code execution with a system of instruction
+ prefetch and cache lines.
+
+ [..] The FLASH main features are:
+ (+) Flash memory read operations
+ (+) Flash memory program/erase operations
+ (+) Program and Erase suspension
+ (+) Read / write protections (2 areas per features)
+ (+) CPU2 Security area
+ (+) Option bytes programming
+ (+) Prefetch on CPU1 I-Code and CPU2 S-bus
+ (+) 32 instruction cache lines of 4*64 bits on I-Code for CPU1
+ (+) 8 data cache lines of 4*64 bits on D-Code for CPU1
+ (+) 4 instruction cache lines of 1*64 bits on S-bus for CPU2
+ (+) 4 data cache lines of 1*64 bits on S-Bus for CPU2
+ (+) Error code correction (ECC) : Data in flash are 72-bits word
+ (8 bits added per double word)
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver provides functions and macros to configure and program the FLASH
+ memory of all STM32WBxx devices.
+
+ (#) Flash Memory IO Programming functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Program functions: double word and fast program (full row programming)
+ (++) There are two modes of programming:
+ (+++) Polling mode using HAL_FLASH_Program() function
+ (+++) Interrupt mode using HAL_FLASH_Program_IT() function
+
+ (#) Interrupts and flags management functions:
+ (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
+ (++) Callback functions are called when the flash operations are finished :
+ HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
+ HAL_FLASH_OperationErrorCallback()
+ (++) Get error flag status by calling HAL_GetError()
+
+ (#) Option bytes management functions :
+ (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
+ HAL_FLASH_OB_Lock() functions
+ (++) Launch the reload of the option bytes using HAL_FLASH_OB_Launch() function.
+ In this case, a reset is generated
+
+ [..]
+ In addition to these functions, this driver includes a set of macros allowing
+ to handle the following operations:
+ (+) Set the latency
+ (+) Enable/Disable the prefetch buffer
+ (+) Enable/Disable the suspend program or erase request
+ (+) Enable/Disable the Instruction cache and the Data cache
+ (+) Reset the Instruction cache and the Data cache
+ (+) Enable/Disable the Flash interrupts
+ (+) Monitor the Flash flags status
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASH FLASH
+ * @brief FLASH HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @addtogroup FLASH_Private_Constants
+ * @{
+ */
+#define FLASH_NB_DOUBLE_WORDS_IN_ROW 64
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup FLASH_Private_Variables FLASH Private Variables
+ * @{
+ */
+/**
+ * @brief Variable used for Program/Erase sectors under interruption
+ */
+FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \
+ .ErrorCode = HAL_FLASH_ERROR_NONE, \
+ .ProcedureOnGoing = 0U, \
+ .Address = 0U, \
+ .Page = 0U, \
+ .NbPagesToErase = 0U
+ };
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASH_Private_Functions FLASH Private Functions
+ * @{
+ */
+static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
+static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup FLASH_Exported_Functions FLASH Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
+ * @brief Programming operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Programming operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the FLASH
+ program operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Program double word or fast program of a row at a specified address.
+ * @note Before any operation, it is possible to check there is no operation suspended
+ * by call HAL_FLASHEx_IsOperationSuspended()
+ * @param TypeProgram Indicate the way to program at a specified address
+ * This parameter can be a value of @ref FLASH_TYPE_PROGRAM
+ * @param Address Specifies the address to be programmed.
+ * @param Data Specifies the data to be programmed
+ * This parameter is the data for the double word program and the address where
+ * are stored the data for the row fast program.
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+ assert_param(IS_ADDR_ALIGNED_64BITS(Address));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Verify that next operation can be proceed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ if (status == HAL_OK)
+ {
+ if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+ /* Program double-word (64-bit) at a specified address */
+ FLASH_Program_DoubleWord(Address, Data);
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_FAST_PROGRAM_ADDRESS(Address));
+
+ /* Fast program a 64 row double-word (64-bit) at a specified address */
+ FLASH_Program_Fast(Address, (uint32_t)Data);
+ }
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ /* If the program operation is completed, disable the PG or FSTPG Bit */
+ CLEAR_BIT(FLASH->CR, TypeProgram);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ /* return status */
+ return status;
+}
+
+/**
+ * @brief Program double word or fast program of a row at a specified address with interrupt enabled.
+ * @note Before any operation, it is possible to check there is no operation suspended
+ * by call HAL_FLASHEx_IsOperationSuspended()
+ * @param TypeProgram Indicate the way to program at a specified address.
+ * This parameter can be a value of @ref FLASH_TYPE_PROGRAM
+ * @param Address Specifies the address to be programmed.
+ * @param Data Specifies the data to be programmed
+ * This parameter is the data for the double word program and the address where
+ * are stored the data for the row fast program.
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+ assert_param(IS_ADDR_ALIGNED_64BITS(Address));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Verify that next operation can be proceed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+ else
+ {
+ /* Set internal variables used by the IRQ handler */
+ pFlash.ProcedureOnGoing = TypeProgram;
+ pFlash.Address = Address;
+
+ /* Enable End of Operation and Error interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
+
+ if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+ /* Program double-word (64-bit) at a specified address */
+ FLASH_Program_DoubleWord(Address, Data);
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_FAST_PROGRAM_ADDRESS(Address));
+
+ /* Fast program a 64 row double-word (64-bit) at a specified address */
+ FLASH_Program_Fast(Address, (uint32_t)Data);
+ }
+ }
+
+ /* return status */
+ return status;
+}
+
+/**
+ * @brief Handle FLASH interrupt request.
+ * @retval None
+ */
+void HAL_FLASH_IRQHandler(void)
+{
+ uint32_t param = 0xFFFFFFFFU;
+ uint32_t error;
+
+ /* Check FLASH operation error flags */
+ error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);
+
+ /* Clear Current operation */
+ CLEAR_BIT(FLASH->CR, pFlash.ProcedureOnGoing);
+
+ /* A] Set parameter for user or error callbacks */
+ /* check operation was a program or erase */
+ if ((pFlash.ProcedureOnGoing & (FLASH_TYPEPROGRAM_DOUBLEWORD | FLASH_TYPEPROGRAM_FAST)) != 0U)
+ {
+ /* return address being programmed */
+ param = pFlash.Address;
+ }
+ else if ((pFlash.ProcedureOnGoing & (FLASH_TYPEERASE_PAGES)) != 0U)
+ {
+ /* return page number being erased */
+ param = pFlash.Page;
+ }
+ else
+ {
+ /* No Procedure on-going */
+ /* Nothing to do, but check error if any */
+ }
+
+ /* B] Check errors */
+ if (error != 0U)
+ {
+ /*Save the error code*/
+ pFlash.ErrorCode |= error;
+
+ /* clear error flags */
+ __HAL_FLASH_CLEAR_FLAG(error);
+
+ /*Stop the procedure ongoing*/
+ pFlash.ProcedureOnGoing = FLASH_TYPENONE;
+
+ /* Error callback */
+ HAL_FLASH_OperationErrorCallback(param);
+ }
+
+ /* C] Check FLASH End of Operation flag */
+ if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+
+ if (pFlash.ProcedureOnGoing == FLASH_TYPEERASE_PAGES)
+ {
+ /* Nb of pages to erased can be decreased */
+ pFlash.NbPagesToErase--;
+
+ /* Check if there are still pages to erase*/
+ if (pFlash.NbPagesToErase != 0U)
+ {
+ /* Increment page number */
+ pFlash.Page++;
+ FLASH_PageErase(pFlash.Page);
+ }
+ else
+ {
+ /* No more pages to erase: stop erase pages procedure */
+ pFlash.ProcedureOnGoing = FLASH_TYPENONE;
+ }
+ }
+ else
+ {
+ /*Stop the ongoing procedure */
+ pFlash.ProcedureOnGoing = FLASH_TYPENONE;
+ }
+
+ /* User callback */
+ HAL_FLASH_EndOfOperationCallback(param);
+ }
+
+ if (pFlash.ProcedureOnGoing == FLASH_TYPENONE)
+ {
+ /* Disable End of Operation and Error interrupts */
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+}
+
+/**
+ * @brief FLASH end of operation interrupt callback.
+ * @param ReturnValue The value saved in this parameter depends on the ongoing procedure
+ * Page Erase: Page which has been erased
+ * Program: Address which was selected for data program
+ * @retval None
+ */
+__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FLASH operation error interrupt callback.
+ * @param ReturnValue The value saved in this parameter depends on the ongoing procedure
+ * Page Erase: Page number which returned an error
+ * Program: Address which was selected for data program
+ * @retval None
+ */
+__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_FLASH_OperationErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
+ * @brief Management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the FLASH
+ memory operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Unlock the FLASH control register access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Unlock(void)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
+ {
+ /* Authorize the FLASH Registers access */
+ WRITE_REG(FLASH->KEYR, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR, FLASH_KEY2);
+
+ /* verify Flash is unlock */
+ if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Lock the FLASH control register access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Lock(void)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Set the LOCK Bit to lock the FLASH Registers access */
+ /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */
+ SET_BIT(FLASH->CR, FLASH_CR_LOCK);
+
+ /* verify Flash is locked */
+ if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U)
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unlock the FLASH Option Bytes Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */
+ if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U)
+ {
+ /* Authorizes the Option Byte register programming */
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
+
+ /* verify option bytes are unlocked */
+ if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0U)
+ {
+ status = HAL_OK;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Lock the FLASH Option Bytes Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
+ /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
+
+ /* verify option bytes are lock */
+ if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0U)
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Launch the option byte loading.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
+{
+ /* Set the bit to force the option byte reloading */
+ /* The OB launch is done from the same register either from CPU1 or CPU2 */
+ SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
+
+ /* We should not reach here : Option byte launch generates Option byte reset
+ so return error */
+ return HAL_ERROR;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral Errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time Errors of the FLASH peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Get the specific FLASH error flag.
+ * @retval FLASH_ErrorCode The returned value can be
+ * @arg @ref HAL_FLASH_ERROR_NONE No error set
+ * @arg @ref HAL_FLASH_ERROR_OP FLASH Operation error
+ * @arg @ref HAL_FLASH_ERROR_PROG FLASH Programming error
+ * @arg @ref HAL_FLASH_ERROR_WRP FLASH Write protection error
+ * @arg @ref HAL_FLASH_ERROR_PGA FLASH Programming alignment error
+ * @arg @ref HAL_FLASH_ERROR_SIZ FLASH Size error
+ * @arg @ref HAL_FLASH_ERROR_PGS FLASH Programming sequence error
+ * @arg @ref HAL_FLASH_ERROR_MIS FLASH Fast programming data miss error
+ * @arg @ref HAL_FLASH_ERROR_FAST FLASH Fast programming error
+ * @arg @ref HAL_FLASH_ERROR_RD FLASH Read Protection error (PCROP)
+ * @arg @ref HAL_FLASH_ERROR_OPTV FLASH Option validity error
+ */
+uint32_t HAL_FLASH_GetError(void)
+{
+ return pFlash.ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @addtogroup FLASH_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Wait for a FLASH operation to complete.
+ * @param Timeout Maximum flash operation timeout
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
+{
+ uint32_t error;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
+ Even if the FLASH operation fails, the BUSY flag will be reset and an error
+ flag will be set */
+ while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
+ {
+ if ((HAL_GetTick() - tickstart) >= Timeout)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check FLASH operation error flags */
+ error = FLASH->SR;
+
+ /* Check FLASH End of Operation flag */
+ if ((error & FLASH_FLAG_EOP) != 0U)
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ }
+
+ /* Workaround for BZ 70309 :
+ - OPTVERR is always set at power-up due to failure of engi bytes checking
+ - FLASH_WaitForLastOperation() is called at the beginning of erase or program
+ operations, so the bit will be clear when performing first operation */
+ if ((error & FLASH_FLAG_OPTVERR) != 0U)
+ {
+ /* Clear FLASH OPTVERR bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
+
+ /* Clear OPTVERR bit in "error" variable to not treat it as error */
+ error &= ~FLASH_FLAG_OPTVERR;
+ }
+
+ /* Now update error variable to only error value */
+ error &= FLASH_FLAG_SR_ERRORS;
+
+ /* clear error flags */
+ __HAL_FLASH_CLEAR_FLAG(error);
+
+ if (error != 0U)
+ {
+ /*Save the error code*/
+ pFlash.ErrorCode = error;
+
+ return HAL_ERROR;
+ }
+
+ /* Wait for control register to be written */
+ while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY))
+ {
+ if ((HAL_GetTick() - tickstart) >= Timeout)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Program double-word (64-bit) at a specified address.
+ * @param Address Specifies the address to be programmed.
+ * @param Data Specifies the data to be programmed.
+ * @retval None
+ */
+static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
+{
+ /* Set PG bit */
+ SET_BIT(FLASH->CR, FLASH_CR_PG);
+
+ /* Program first word */
+ *(uint32_t *)Address = (uint32_t)Data;
+
+ /* Barrier to ensure programming is performed in 2 steps, in right order
+ (independently of compiler optimization behavior) */
+ __ISB();
+
+ /* Program second word */
+ *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);
+}
+
+/**
+ * @brief Fast program a 32 row double-word (64-bit) at a specified address.
+ * @param Address Specifies the address to be programmed.
+ * @param DataAddress Specifies the address where the data are stored.
+ * @retval None
+ */
+static __RAM_FUNC void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)
+{
+ uint8_t row_index = (2 * FLASH_NB_DOUBLE_WORDS_IN_ROW);
+ __IO uint32_t *dest_addr = (__IO uint32_t *)Address;
+ __IO uint32_t *src_addr = (__IO uint32_t *)DataAddress;
+ uint32_t primask_bit;
+
+ /* Set FSTPG bit */
+ SET_BIT(FLASH->CR, FLASH_CR_FSTPG);
+
+ /* Enter critical section: row programming should not be longer than 7 ms */
+ primask_bit = __get_PRIMASK();
+ __disable_irq();
+
+ /* Program the double word of the row */
+ do
+ {
+ *dest_addr = *src_addr;
+ dest_addr++;
+ src_addr++;
+ row_index--;
+ } while (row_index != 0U);
+
+ /* wait for BSY in order to be sure that flash operation is ended before
+ allowing prefetch in flash. Timeout does not return status, as it will
+ be anyway done later */
+ while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != 0U)
+ {
+ }
+
+ /* Exit critical section: restore previous priority mask */
+ __set_PRIMASK(primask_bit);
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c
new file mode 100644
index 0000000..e54df67
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c
@@ -0,0 +1,1061 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_flash_ex.c
+ * @author MCD Application Team
+ * @brief Extended FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the FLASH extended peripheral:
+ * + Extended programming operations functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### Flash Extended features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the FLASH interface for STM32WBxx
+ devices contains the following additional features
+
+ (+) Capacity up to 1 Mbyte with single bank architecture supporting read-while-write
+ capability (RWW)
+ (+) Single bank memory organization
+ (+) PCROP protection
+ (+) WRP protection
+ (+) CPU2 Security area
+ (+) Program Erase Suspend feature
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure and program the FLASH memory
+ of all STM32WBxx devices. It includes
+ (#) Flash Memory Erase functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Erase function: Erase page, erase all sectors
+ (++) There are two modes of erase :
+ (+++) Polling Mode using HAL_FLASHEx_Erase()
+ (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
+
+ (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to :
+ (++) Set/Reset the write protection (per 4 KByte)
+ (++) Set the Read protection Level
+ (++) Program the user Option Bytes
+ (++) Configure the PCROP protection (per 2 KByte)
+ (++) Configure the IPCC Buffer start Address
+ (++) Configure the CPU2 boot region and reset vector start Address
+ (++) Configure the Flash and SRAM2 secure area
+
+ (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to :
+ (++) Get the value of a write protection area
+ (++) Know if the read protection is activated
+ (++) Get the value of the user Option Bytes
+ (++) Get the value of a PCROP area
+ (++) Get the IPCC Buffer start Address
+ (++) Get the CPU2 boot region and reset vector start Address
+ (++) Get the Flash and SRAM2 secure area
+
+ (#) Flash Suspend, Allow functions:
+ (++) Suspend or Allow new program or erase operation request using HAL_FLASHEx_SuspendOperation() and
+ HAL_FLASHEx_AllowOperation() functions
+
+ (#) Check is flash content is empty or not using HAL_FLASHEx_FlashEmptyCheck().
+ and modify this setting (for flash loader purpose e.g.) using
+ HAL_FLASHEx_ForceFlashEmpty().
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASHEx FLASHEx
+ * @brief FLASH Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
+ * @{
+ */
+static void FLASH_AcknowledgePageErase(void);
+static void FLASH_FlushCaches(void);
+static void FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
+static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel);
+static void FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr,
+ uint32_t PCROP1AEndAddr);
+static void FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr);
+static void FLASH_OB_IPCCBufferAddrConfig(uint32_t IPCCDataBufAddr);
+static void FLASH_OB_SecureConfig(FLASH_OBProgramInitTypeDef *pOBParam);
+static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset);
+static uint32_t FLASH_OB_GetRDP(void);
+static uint32_t FLASH_OB_GetUser(void);
+static void FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr,
+ uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr);
+static uint32_t FLASH_OB_GetIPCCBufferAddr(void);
+static void FLASH_OB_GetSecureMemoryConfig(uint32_t *SecureFlashStartAddr, uint32_t *SecureRAM2aStartAddr,
+ uint32_t *SecureRAM2bStartAddr, uint32_t *SecureMode);
+static void FLASH_OB_GetC2BootResetConfig(uint32_t *C2BootResetVectAddr, uint32_t *C2BootResetRegion);
+static HAL_StatusTypeDef FLASH_OB_ProceedWriteOperation(void);
+/**
+ * @}
+ */
+
+/* Exported functions -------------------------------------------------------*/
+/** @defgroup FLASHEx_Exported_Functions FLASH Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
+ * @brief Extended IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended programming operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the Extended FLASH
+ programming operations Operations.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Perform an erase of the specified FLASH memory pages.
+ * @note Before any operation, it is possible to check there is no operation suspended
+ * by call HAL_FLASHEx_IsOperationSuspended()
+ * @param[in] pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ * @param[out] PageError Pointer to variable that contains the configuration
+ * information on faulty page in case of error (0xFFFFFFFF means that all
+ * the pages have been correctly erased)
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
+{
+ HAL_StatusTypeDef status;
+ uint32_t index;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Verify that next operation can be proceed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ if (status == HAL_OK)
+ {
+ if (pEraseInit->TypeErase == FLASH_TYPEERASE_PAGES)
+ {
+ /*Initialization of PageError variable*/
+ *PageError = 0xFFFFFFFFU;
+
+ for (index = pEraseInit->Page; index < (pEraseInit->Page + pEraseInit->NbPages); index++)
+ {
+ /* Start erase page */
+ FLASH_PageErase(index);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ if (status != HAL_OK)
+ {
+ /* In case of error, stop erase procedure and return the faulty address */
+ *PageError = index;
+ break;
+ }
+ }
+
+ /* If operation is completed or interrupted, disable the Page Erase Bit */
+ FLASH_AcknowledgePageErase();
+ }
+
+ /* Flush the caches to be sure of the data consistency */
+ FLASH_FlushCaches();
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Perform an erase of the specified FLASH memory pages with interrupt enabled.
+ * @note Before any operation, it is possible to check there is no operation suspended
+ * by call HAL_FLASHEx_IsOperationSuspended()
+ * @param pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* save procedure for interrupt treatment */
+ pFlash.ProcedureOnGoing = pEraseInit->TypeErase;
+
+ /* Verify that next operation can be proceed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+ else
+ {
+ /* Enable End of Operation and Error interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
+
+ if (pEraseInit->TypeErase == FLASH_TYPEERASE_PAGES)
+ {
+ /* Erase by page to be done */
+ pFlash.NbPagesToErase = pEraseInit->NbPages;
+ pFlash.Page = pEraseInit->Page;
+
+ /*Erase 1st page and wait for IT */
+ FLASH_PageErase(pEraseInit->Page);
+ }
+ }
+
+ /* return status */
+ return status;
+}
+
+/**
+ * @brief Program Option bytes.
+ * @param pOBInit Pointer to an @ref FLASH_OBProgramInitTypeDef structure that
+ * contains the configuration information for the programming.
+ * @note To configure any option bytes, the option lock bit OPTLOCK must be
+ * cleared with the call of @ref HAL_FLASH_OB_Unlock() function.
+ * @note New option bytes configuration will be taken into account only
+ * - after an option bytes launch through the call of @ref HAL_FLASH_OB_Launch()
+ * - a Power On Reset
+ * - an exit from Standby or Shutdown mode.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ uint32_t optr;
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Write protection configuration */
+ if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0U)
+ {
+ /* Configure of Write protection on the selected area */
+ FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset);
+ }
+
+ /* Option register */
+ if ((pOBInit->OptionType & (OPTIONBYTE_RDP | OPTIONBYTE_USER)) == (OPTIONBYTE_RDP | OPTIONBYTE_USER))
+ {
+ /* Fully modify OPTR register with RDP & user data */
+ FLASH_OB_OptrConfig(pOBInit->UserType, pOBInit->UserConfig, pOBInit->RDPLevel);
+ }
+ else if ((pOBInit->OptionType & OPTIONBYTE_RDP) != 0U)
+ {
+ /* Only modify RDP so get current user data */
+ optr = FLASH_OB_GetUser();
+
+ /* Remove BOR LEVEL User Type*/
+ optr &= ~OB_USER_BOR_LEV;
+
+ FLASH_OB_OptrConfig(optr, optr, pOBInit->RDPLevel);
+ }
+ else if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0U)
+ {
+ /* Only modify user so get current RDP level */
+ optr = FLASH_OB_GetRDP();
+ FLASH_OB_OptrConfig(pOBInit->UserType, pOBInit->UserConfig, optr);
+ }
+ else
+ {
+ /* Do Nothing */
+ }
+
+ /* PCROP Configuration */
+ if ((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0U)
+ {
+ /* Check the parameters */
+ assert_param(IS_OB_PCROP_CONFIG(pOBInit->PCROPConfig));
+
+ if ((pOBInit->PCROPConfig & (OB_PCROP_ZONE_A | OB_PCROP_RDP_ERASE)) != 0U)
+ {
+ /* Configure the Zone 1A Proprietary code readout protection */
+ FLASH_OB_PCROP1AConfig(pOBInit->PCROPConfig, pOBInit->PCROP1AStartAddr, pOBInit->PCROP1AEndAddr);
+ }
+
+ if ((pOBInit->PCROPConfig & OB_PCROP_ZONE_B) != 0U)
+ {
+ /* Configure the Zone 1B Proprietary code readout protection */
+ FLASH_OB_PCROP1BConfig(pOBInit->PCROP1BStartAddr, pOBInit->PCROP1BEndAddr);
+ }
+ }
+
+ /* Secure mode and CPU2 Boot Vector */
+ if ((pOBInit->OptionType & (OPTIONBYTE_SECURE_MODE | OPTIONBYTE_C2_BOOT_VECT)) != 0U)
+ {
+ /* Set the secure flash and SRAM memory start address */
+ FLASH_OB_SecureConfig(pOBInit);
+ }
+
+ /* IPCC mailbox data buffer address */
+ if ((pOBInit->OptionType & OPTIONBYTE_IPCC_BUF_ADDR) != 0U)
+ {
+ /* Configure the IPCC data buffer address */
+ FLASH_OB_IPCCBufferAddrConfig(pOBInit->IPCCdataBufAddr);
+ }
+
+ /* Proceed the OB Write Operation */
+ status = FLASH_OB_ProceedWriteOperation();
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ /* return status */
+ return status;
+}
+
+/**
+ * @brief Get the Option bytes configuration.
+ * @note warning: this API only read flash register, it does not reflect any
+ * change that would have been programmed between previous Option byte
+ * loading and current call.
+ * @param pOBInit Pointer to an @ref FLASH_OBProgramInitTypeDef structure that contains the
+ * configuration information. The fields pOBInit->WRPArea and
+ * pOBInit->PCROPConfig should indicate which area is requested
+ * for the WRP and PCROP.
+ * @retval None
+ */
+void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ pOBInit->OptionType = OPTIONBYTE_ALL;
+
+ if ((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB))
+ {
+ /* Get write protection on the selected area */
+ FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));
+ }
+
+ /* Get Read protection level */
+ pOBInit->RDPLevel = FLASH_OB_GetRDP();
+
+ /* Get the user option bytes */
+ pOBInit->UserConfig = FLASH_OB_GetUser();
+ pOBInit->UserType = OB_USER_ALL;
+
+ /* Get the Zone 1A and 1B Proprietary code readout protection */
+ FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROP1AStartAddr), &(pOBInit->PCROP1AEndAddr),
+ &(pOBInit->PCROP1BStartAddr), &(pOBInit->PCROP1BEndAddr));
+ pOBInit->PCROPConfig |= (OB_PCROP_ZONE_A | OB_PCROP_ZONE_B);
+
+ /* Get the IPCC start Address */
+ pOBInit->IPCCdataBufAddr = FLASH_OB_GetIPCCBufferAddr();
+
+ /* Get the Secure Flash start address, Secure Backup RAM2a start address, Secure non-Backup RAM2b start address and the Security Mode, */
+ FLASH_OB_GetSecureMemoryConfig(&(pOBInit->SecureFlashStartAddr), &(pOBInit->SecureRAM2aStartAddr),
+ &(pOBInit->SecureRAM2bStartAddr), &(pOBInit->SecureMode));
+
+ /* Get the M0+ Secure Boot reset vector and Secure Boot memory selection */
+ FLASH_OB_GetC2BootResetConfig(&(pOBInit->C2SecureBootVectAddr), &(pOBInit->C2BootRegion));
+}
+
+/**
+ * @brief Flash Empty check
+ * @note This API checks if first location in Flash is programmed or not.
+ * This check is done once by Option Byte Loader.
+ * @retval Returned value can be one of the following values:
+ * @arg @ref FLASH_PROG_NOT_EMPTY 1st location in Flash is programmed
+ * @arg @ref FLASH_PROG_EMPTY 1st location in Flash is empty
+ */
+uint32_t HAL_FLASHEx_FlashEmptyCheck(void)
+{
+ return (READ_BIT(FLASH->ACR, FLASH_ACR_EMPTY));
+}
+
+
+/**
+ * @brief Force Empty check value.
+ * @note Allows to modify program empty check value in order to force this
+ * information in Flash Interface, for all next reset that do not launch
+ * Option Byte Loader.
+ * @param FlashEmpty Specifies the empty check value
+ * This parameter can be one of the following values:
+ * @arg @ref FLASH_PROG_NOT_EMPTY 1st location in Flash is programmed
+ * @arg @ref FLASH_PROG_EMPTY 1st location in Flash is empty
+ * @retval None
+ */
+void HAL_FLASHEx_ForceFlashEmpty(uint32_t FlashEmpty)
+{
+ assert_param(IS_FLASH_EMPTY_CHECK(FlashEmpty));
+
+ MODIFY_REG(FLASH->ACR, FLASH_ACR_EMPTY, FlashEmpty);
+}
+
+/**
+ * @brief Suspend new program or erase operation request.
+ * @note Any new Flash program and erase operation on both CPU side will be suspended
+ * until this bit and the same bit in Flash CPU2 access control register (FLASH_C2ACR) are
+ * cleared. The PESD bit in both the Flash status register (FLASH_SR) and Flash
+ * CPU2 status register (FLASH_C2SR) register will be set when at least one PES
+ * bit in FLASH_ACR or FLASH_C2ACR is set.
+ * @retval None
+ */
+void HAL_FLASHEx_SuspendOperation(void)
+{
+ SET_BIT(FLASH->ACR, FLASH_ACR_PES);
+}
+
+/**
+ * @brief Allow new program or erase operation request.
+ * @note Any new Flash program and erase operation on both CPU side will be allowed
+ * until one of this bit or the same bit in Flash CPU2 access control register (FLASH_C2ACR) is
+ * set. The PESD bit in both the Flash status register (FLASH_SR) and Flash
+ * CPU2 status register (FLASH_C2SR) register will be clear when both PES
+ * bit in FLASH_ACR or FLASH_C2ACR is cleared.
+ * @retval None
+ */
+void HAL_FLASHEx_AllowOperation(void)
+{
+ CLEAR_BIT(FLASH->ACR, FLASH_ACR_PES);
+}
+
+/**
+ * @brief Check if new program or erase operation request from CPU1 or CPU2 is suspended
+ * @note Any new Flash program and erase operation on both CPU side will be allowed
+ * until one of this bit or the same bit in Flash CPU2 access control register (FLASH_C2ACR) is
+ * set. The PESD bit in both the Flash status register (FLASH_SR) and Flash
+ * CPU2 status register (FLASH_C2SR) register will be cleared when both PES
+ * bit in FLASH_ACR and FLASH_C2ACR are cleared.
+ * @retval Status
+ * - 0 : No suspended flash operation
+ * - 1 : Flash operation is suspended
+ */
+uint32_t HAL_FLASHEx_IsOperationSuspended(void)
+{
+ uint32_t status = 0U;
+
+ if (READ_BIT(FLASH->SR, FLASH_SR_PESD) == FLASH_SR_PESD)
+ {
+ status = 1U;
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup FLASHEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Erase the specified FLASH memory page.
+ * @param Page FLASH page to erase
+ * This parameter must be a value between 0 and (max number of pages in Flash - 1)
+ * @retval None
+ */
+void FLASH_PageErase(uint32_t Page)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_PAGE(Page));
+
+ /* Proceed to erase the page */
+ MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((Page << FLASH_CR_PNB_Pos) | FLASH_CR_PER | FLASH_CR_STRT));
+}
+
+/**
+ * @brief Flush the instruction and data caches.
+ * @retval None
+ */
+static void FLASH_FlushCaches(void)
+{
+ /* Flush instruction cache */
+ if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) == FLASH_ACR_ICEN)
+ {
+ /* Disable instruction cache */
+ __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+ /* Reset instruction cache */
+ __HAL_FLASH_INSTRUCTION_CACHE_RESET();
+ /* Enable instruction cache */
+ __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+ }
+
+ /* Flush data cache */
+ if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) == FLASH_ACR_DCEN)
+ {
+ /* Disable data cache */
+ __HAL_FLASH_DATA_CACHE_DISABLE();
+ /* Reset data cache */
+ __HAL_FLASH_DATA_CACHE_RESET();
+ /* Enable data cache */
+ __HAL_FLASH_DATA_CACHE_ENABLE();
+ }
+}
+
+/**
+ * @brief Acknlowldge the page erase operation.
+ * @retval None
+ */
+static void FLASH_AcknowledgePageErase(void)
+{
+ CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
+}
+
+/**
+ * @brief Configure the write protection of the desired pages.
+ * @note When WRP is active in a zone, it cannot be erased or programmed.
+ * Consequently, a software mass erase cannot be performed if one zone
+ * is write-protected.
+ * @note When the memory read protection level is selected (RDP level = 1),
+ * it is not possible to program or erase Flash memory if the CPU debug
+ * features are connected (JTAG or single wire) or boot code is being
+ * executed from RAM or System flash, even if WRP is not activated.
+ * @note To configure the WRP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the @ref HAL_FLASH_OB_Unlock() function.
+ * @note To validate the WRP options, the option bytes must be reloaded
+ * through the call of the @ref HAL_FLASH_OB_Launch() function.
+ * @param WRPArea Specifies the area to be configured.
+ * This parameter can be one of the following values:
+ * @arg @ref OB_WRPAREA_BANK1_AREAA Flash Bank 1 Area A
+ * @arg @ref OB_WRPAREA_BANK1_AREAB Flash Bank 1 Area B
+ * @param WRPStartOffset Specifies the start page of the write protected area
+ * This parameter can be page number between 0 and (max number of pages in the Flash - 1)
+ * @param WRDPEndOffset Specifies the end page of the write protected area
+ * This parameter can be page number between WRPStartOffset and (max number of pages in the Flash - 1)
+ * @retval None
+ */
+static void FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_WRPAREA(WRPArea));
+ assert_param(IS_FLASH_PAGE(WRPStartOffset));
+ assert_param(IS_FLASH_PAGE(WRDPEndOffset));
+
+ /* Configure the write protected area */
+ if (WRPArea == OB_WRPAREA_BANK1_AREAA)
+ {
+ MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END),
+ (WRPStartOffset | (WRDPEndOffset << FLASH_WRP1AR_WRP1A_END_Pos)));
+ }
+ else /* OB_WRPAREA_BANK1_AREAB */
+ {
+ MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END),
+ (WRPStartOffset | (WRDPEndOffset << FLASH_WRP1AR_WRP1A_END_Pos)));
+ }
+}
+
+/**
+ * @brief Set user & RDP configuration
+ * @note !!! Warning : When enabling OB_RDP level 2 it's no more possible
+ * to go back to level 1 or 0 !!!
+ * @param UserType The FLASH User Option Bytes to be modified
+ * This parameter can be a combination of all the following values:
+ * @arg @ref OB_USER_BOR_LEV or @ref OB_USER_nRST_STOP or @ref OB_USER_nRST_STDBY or
+ * @arg @ref OB_USER_nRST_SHDW or @ref OB_USER_IWDG_SW or @ref OB_USER_IWDG_STOP or
+ * @arg @ref OB_USER_IWDG_STDBY or @ref OB_USER_WWDG_SW or @ref OB_USER_nBOOT1 or
+ * @arg @ref OB_USER_SRAM2PE or @ref OB_USER_SRAM2RST or @ref OB_USER_nSWBOOT0 or
+ * @arg @ref OB_USER_nBOOT0 or @ref OB_USER_AGC_TRIM or @ref OB_USER_ALL
+ * @param UserConfig The FLASH User Option Bytes values.
+ * This parameter can be a combination of all the following values:
+ * @arg @ref OB_BOR_LEVEL_0 or @ref OB_BOR_LEVEL_1 or ... or @ref OB_BOR_LEVEL_4
+ * @arg @ref OB_STOP_RST or @ref OB_STOP_NORST
+ * @arg @ref OB_STANDBY_RST or @ref OB_STANDBY_NORST
+ * @arg @ref OB_SHUTDOWN_RST or @ref OB_SHUTDOWN_NORST
+ * @arg @ref OB_IRH_ENABLE or @ref OB_IRH_DISABLE (*)
+ * @arg @ref OB_IWDG_SW or @ref OB_IWDG_HW
+ * @arg @ref OB_IWDG_STOP_FREEZE or @ref OB_IWDG_STOP_RUN
+ * @arg @ref OB_IWDG_STDBY_FREEZE or @ref OB_IWDG_STDBY_RUN
+ * @arg @ref OB_WWDG_SW or @ref OB_WWDG_HW
+ * @arg @ref OB_BOOT1_SRAM or @ref OB_BOOT1_SYSTEM
+ * @arg @ref OB_SRAM2_PARITY_ENABLE or @ref OB_SRAM2_PARITY_DISABLE
+ * @arg @ref OB_SRAM2_RST_ERASE or @ref OB_SRAM2_RST_NOT_ERASE
+ * @arg @ref OB_BOOT0_FROM_OB or @ref OB_BOOT0_FROM_PIN
+ * @arg @ref OB_BOOT0_RESET or @ref OB_BOOT0_SET
+ * @arg @ref OB_RESET_MODE_INPUT_ONLY or @ref OB_RESET_MODE_GPIO or @ref OB_RESET_MODE_INPUT_OUTPUT (*)
+ * @arg @ref OB_AGC_TRIM_0 or @ref OB_AGC_TRIM_1 or ... or @ref OB_AGC_TRIM_7
+ * @param RDPLevel: specifies the read protection level.
+ * This parameter can be one of the following values:
+ * @arg @ref OB_RDP_LEVEL_0 No protection
+ * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
+ * @arg @ref OB_RDP_LEVEL_2 Full chip protection
+ * @retval None
+ */
+static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel)
+{
+ uint32_t optr;
+
+ /* Check the parameters */
+ assert_param(IS_OB_USER_TYPE(UserType));
+ assert_param(IS_OB_USER_CONFIG(UserType, UserConfig));
+ assert_param(IS_OB_RDP_LEVEL(RDPLevel));
+
+ /* Configure the RDP level in the option bytes register */
+ optr = FLASH->OPTR;
+ optr &= ~(UserType | FLASH_OPTR_RDP);
+ FLASH->OPTR = (optr | UserConfig | RDPLevel);
+}
+
+/**
+ * @brief Configure the Zone 1A Proprietary code readout protection of the desired addresses,
+ * and erase configuration on RDP regression.
+ * @note To configure the PCROP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the @ref HAL_FLASH_OB_Unlock() function.
+ * @note To validate the PCROP options, the option bytes must be reloaded
+ * through the call of the @ref HAL_FLASH_OB_Launch() function.
+ * @param PCROPConfig: specifies the erase configuration (OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE)
+ * on RDP level 1 regression.
+ * @param PCROP1AStartAddr Specifies the Zone 1A Start address of the Proprietary code readout protection
+ * This parameter can be an address between begin and end of the flash
+ * @param PCROP1AEndAddr Specifies the Zone 1A end address of the Proprietary code readout protection
+ * This parameter can be an address between PCROP1AStartAddr and end of the flash
+ * @retval None
+ */
+static void FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr, uint32_t PCROP1AEndAddr)
+{
+ uint32_t startoffset;
+ uint32_t endoffset;
+ uint32_t pcrop1aend;
+
+ /* Check the parameters */
+ assert_param(IS_OB_PCROP_CONFIG(PCROPConfig));
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1AStartAddr));
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1AEndAddr));
+
+ /* get pcrop 1A end register */
+ pcrop1aend = FLASH->PCROP1AER;
+
+ /* Configure the Proprietary code readout protection offset */
+ if ((PCROPConfig & OB_PCROP_ZONE_A) != 0U)
+ {
+ /* Compute offset depending on pcrop granularity */
+ startoffset = ((PCROP1AStartAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET); /* 2K pages */
+ endoffset = ((PCROP1AEndAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET); /* 2K pages */
+
+ /* Set Zone A start offset */
+ WRITE_REG(FLASH->PCROP1ASR, startoffset);
+
+ /* Set Zone A end offset */
+ pcrop1aend &= ~FLASH_PCROP1AER_PCROP1A_END;
+ pcrop1aend |= endoffset;
+ }
+
+ /* Set RDP erase protection if needed. This bit is only set & will be reset by mass erase */
+ if ((PCROPConfig & OB_PCROP_RDP_ERASE) != 0U)
+ {
+ pcrop1aend |= FLASH_PCROP1AER_PCROP_RDP;
+ }
+
+ /* set 1A End register */
+ WRITE_REG(FLASH->PCROP1AER, pcrop1aend);
+}
+
+/**
+ * @brief Configure the Zone 1B Proprietary code readout protection of the desired addresses.
+ * @note To configure the PCROP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the @ref HAL_FLASH_OB_Unlock() function.
+ * @note To validate the PCROP options, the option bytes must be reloaded
+ * through the call of the @ref HAL_FLASH_OB_Launch() function.
+ * @param PCROP1BStartAddr Specifies the Zone 1BStart address of the Proprietary code readout protection
+ * This parameter can be an address between begin and end of the flash
+ * @param PCROP1BEndAddr Specifies the Zone 1B end address of the Proprietary code readout protection
+ * This parameter can be an address between PCROP1BStartAddr and end of the flash
+ * @retval None
+ */
+static void FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr)
+{
+ uint32_t startoffset;
+ uint32_t endoffset;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1BStartAddr));
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1BEndAddr));
+
+ /* Compute offset depending on pcrop granularity */
+ startoffset = ((PCROP1BStartAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET); /* 2K pages */
+ endoffset = ((PCROP1BEndAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET); /* 2K pages */
+
+ /* Configure the Proprietary code readout protection start address */
+ WRITE_REG(FLASH->PCROP1BSR, startoffset);
+
+ /* Configure the Proprietary code readout protection end address */
+ WRITE_REG(FLASH->PCROP1BER, endoffset);
+}
+
+/**
+ * @brief Program the FLASH IPCC data buffer address.
+ * @note To configure the extra user option bytes, the option lock bit OPTLOCK must
+ * be cleared with the call of the @ref HAL_FLASH_OB_Unlock() function.
+ * @note To validate the extra user option bytes, the option bytes must be reloaded
+ * through the call of the @ref HAL_FLASH_OB_Launch() function.
+ * @param IPCCDataBufAddr IPCC data buffer start address area in SRAM2
+ * This parameter must be the double-word aligned
+ * @retval None
+ */
+static void FLASH_OB_IPCCBufferAddrConfig(uint32_t IPCCDataBufAddr)
+{
+ assert_param(IS_OB_IPCC_BUF_ADDR(IPCCDataBufAddr));
+
+ /* Configure the option bytes register */
+ WRITE_REG(FLASH->IPCCBR, (uint32_t)((IPCCDataBufAddr - SRAM2A_BASE) >> 4));
+}
+
+/**
+ * @brief Configure the secure start address of the different memories (FLASH and SRAM2),
+ * the secure mode and the CPU2 Secure Boot reset vector
+ * @note To configure the PCROP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the @ref HAL_FLASH_OB_Unlock() function.
+ * @param pOBParam Pointer to an @ref FLASH_OBProgramInitTypeDef structure that
+ * contains the configuration information for the programming
+ * @retval void
+ */
+static void FLASH_OB_SecureConfig(FLASH_OBProgramInitTypeDef *pOBParam)
+{
+ uint32_t sfr_reg_val = READ_REG(FLASH->SFR);
+ uint32_t srrvr_reg_val = READ_REG(FLASH->SRRVR);
+
+ if ((pOBParam->OptionType & OPTIONBYTE_SECURE_MODE) != 0U)
+ {
+ assert_param(IS_OB_SFSA_START_ADDR(pOBParam->SecureFlashStartAddr));
+ assert_param(IS_OB_SBRSA_START_ADDR(pOBParam->SecureRAM2aStartAddr));
+ assert_param(IS_OB_SNBRSA_START_ADDR(pOBParam->SecureRAM2bStartAddr));
+ assert_param(IS_OB_SECURE_MODE(pOBParam->SecureMode));
+
+ /* Configure SFR register content with start PAGE index to secure */
+ MODIFY_REG(sfr_reg_val, FLASH_SFR_SFSA, (((pOBParam->SecureFlashStartAddr - FLASH_BASE) / FLASH_PAGE_SIZE) << FLASH_SFR_SFSA_Pos));
+
+ /* Configure SRRVR register */
+#if defined(FLASH_SRRVR_SBRSA_A)
+ MODIFY_REG(srrvr_reg_val, (FLASH_SRRVR_SBRSA_A | FLASH_SRRVR_SBRSA_B), \
+ (((((pOBParam->SecureRAM2aStartAddr - SRAM2A_BASE) >> SRAM_SECURE_PAGE_GRANULARITY_OFFSET) << FLASH_SRRVR_SBRSA_A_Pos)) | \
+ ((((pOBParam->SecureRAM2bStartAddr - SRAM2B_BASE) >> SRAM_SECURE_PAGE_GRANULARITY_OFFSET) << FLASH_SRRVR_SBRSA_B_Pos))));
+#else
+ MODIFY_REG(srrvr_reg_val, (FLASH_SRRVR_SBRSA | FLASH_SRRVR_SNBRSA), \
+ (((((pOBParam->SecureRAM2aStartAddr - SRAM2A_BASE) >> SRAM_SECURE_PAGE_GRANULARITY_OFFSET) << FLASH_SRRVR_SBRSA_Pos)) | \
+ ((((pOBParam->SecureRAM2bStartAddr - SRAM2B_BASE) >> SRAM_SECURE_PAGE_GRANULARITY_OFFSET) << FLASH_SRRVR_SNBRSA_Pos))));
+#endif /* FLASH_SRRVR_SBRSA_A */
+
+ /* If Full System Secure mode is requested, clear all the corresponding bit */
+ /* Else set the corresponding bit */
+ if (pOBParam->SecureMode == SYSTEM_IN_SECURE_MODE)
+ {
+ CLEAR_BIT(sfr_reg_val, FLASH_SFR_FSD);
+#if defined(FLASH_SRRVR_BRSD_A)
+ CLEAR_BIT(srrvr_reg_val, (FLASH_SRRVR_BRSD_A | FLASH_SRRVR_BRSD_B));
+#else
+ CLEAR_BIT(srrvr_reg_val, (FLASH_SRRVR_BRSD | FLASH_SRRVR_NBRSD));
+#endif /* FLASH_SRRVR_BRSD_A */
+ }
+ else
+ {
+ SET_BIT(sfr_reg_val, FLASH_SFR_FSD);
+#if defined(FLASH_SRRVR_BRSD_A)
+ SET_BIT(srrvr_reg_val, (FLASH_SRRVR_BRSD_A | FLASH_SRRVR_BRSD_B));
+#else
+ SET_BIT(srrvr_reg_val, (FLASH_SRRVR_BRSD | FLASH_SRRVR_NBRSD));
+#endif /* FLASH_SRRVR_BRSD_A */
+ }
+
+ /* Update Flash registers */
+ WRITE_REG(FLASH->SFR, sfr_reg_val);
+ }
+
+ /* Boot vector */
+ if ((pOBParam->OptionType & OPTIONBYTE_C2_BOOT_VECT) != 0U)
+ {
+ /* Check the parameters */
+ assert_param(IS_OB_BOOT_VECTOR_ADDR(pOBParam->C2SecureBootVectAddr));
+ assert_param(IS_OB_BOOT_REGION(pOBParam->C2BootRegion));
+
+ /* Set the boot vector */
+ if (pOBParam->C2BootRegion == OB_C2_BOOT_FROM_FLASH)
+ {
+ MODIFY_REG(srrvr_reg_val, (FLASH_SRRVR_SBRV | FLASH_SRRVR_C2OPT),
+ (((pOBParam->C2SecureBootVectAddr - FLASH_BASE) >> 2) | pOBParam->C2BootRegion));
+ }
+ else
+ {
+ MODIFY_REG(srrvr_reg_val, (FLASH_SRRVR_SBRV | FLASH_SRRVR_C2OPT),
+ (((pOBParam->C2SecureBootVectAddr - SRAM1_BASE) >> 2) | pOBParam->C2BootRegion));
+ }
+ }
+
+ /* Update Flash registers */
+ WRITE_REG(FLASH->SRRVR, srrvr_reg_val);
+}
+
+/**
+ * @brief Return the FLASH Write Protection Option Bytes value.
+ * @param[in] WRPArea Specifies the area to be returned.
+ * This parameter can be one of the following values:
+ * @arg @ref OB_WRPAREA_BANK1_AREAA Flash Bank 1 Area A
+ * @arg @ref OB_WRPAREA_BANK1_AREAB Flash Bank 1 Area B
+ * @param[out] WRPStartOffset Specifies the address where to copied the start page
+ * of the write protected area
+ * @param[out] WRDPEndOffset Specifies the address where to copied the end page of
+ * the write protected area
+ * @retval None
+ */
+static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_WRPAREA(WRPArea));
+
+ /* Get the configuration of the write protected area */
+ if (WRPArea == OB_WRPAREA_BANK1_AREAA)
+ {
+ *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
+ *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos);
+ }
+ else /* OB_WRPAREA_BANK1_AREAB */
+ {
+ *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
+ *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos);
+ }
+}
+
+/**
+ * @brief Return the FLASH Read Protection level.
+ * @retval FLASH ReadOut Protection Status:
+ * This return value can be one of the following values:
+ * @arg @ref OB_RDP_LEVEL_0 No protection
+ * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
+ * @arg @ref OB_RDP_LEVEL_2 Full chip protection
+ */
+static uint32_t FLASH_OB_GetRDP(void)
+{
+ uint32_t rdplvl = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);
+
+ if ((rdplvl != OB_RDP_LEVEL_0) && (rdplvl != OB_RDP_LEVEL_2))
+ {
+ return (OB_RDP_LEVEL_1);
+ }
+ else
+ {
+ return rdplvl;
+ }
+}
+
+/**
+ * @brief Return the FLASH User Option Byte value.
+ * @retval This return value can be a combination of all the following values:
+ * @arg @ref OB_BOR_LEVEL_0 or @ref OB_BOR_LEVEL_1 or ... or @ref OB_BOR_LEVEL_4
+ * @arg @ref OB_STOP_RST or @ref OB_STOP_RST
+ * @arg @ref OB_STANDBY_RST or @ref OB_STANDBY_NORST
+ * @arg @ref OB_SHUTDOWN_RST or @ref OB_SHUTDOWN_NORST
+ * @arg @ref OB_IRH_ENABLE or @ref OB_IRH_DISABLE (*)
+ * @arg @ref OB_IWDG_SW or @ref OB_IWDG_HW
+ * @arg @ref OB_IWDG_STOP_FREEZE or @ref OB_IWDG_STOP_RUN
+ * @arg @ref OB_IWDG_STDBY_FREEZE or @ref OB_IWDG_STDBY_RUN
+ * @arg @ref OB_WWDG_SW or @ref OB_WWDG_HW
+ * @arg @ref OB_BOOT1_SRAM or @ref OB_BOOT1_SYSTEM
+ * @arg @ref OB_SRAM2_PARITY_ENABLE or @ref OB_SRAM2_PARITY_DISABLE
+ * @arg @ref OB_SRAM2_RST_ERASE or @ref OB_SRAM2_RST_NOT_ERASE
+ * @arg @ref OB_BOOT0_FROM_OB or @ref OB_BOOT0_FROM_PIN
+ * @arg @ref OB_BOOT0_RESET or @ref OB_BOOT0_SET
+ * @arg @ref OB_RESET_MODE_INPUT_ONLY or @ref OB_RESET_MODE_GPIO or @ref OB_RESET_MODE_INPUT_OUTPUT (*)
+ * @arg @ref OB_AGC_TRIM_0 or @ref OB_AGC_TRIM_1 or ... or @ref OB_AGC_TRIM_7
+ */
+static uint32_t FLASH_OB_GetUser(void)
+{
+ uint32_t user_config = (READ_REG(FLASH->OPTR) & OB_USER_ALL);
+ CLEAR_BIT(user_config, (FLASH_OPTR_RDP | FLASH_OPTR_ESE));
+
+ return user_config;
+}
+
+/**
+ * @brief Return the FLASH Write Protection Option Bytes value.
+ * @param PCROPConfig [out] Specifies the address where to copied the configuration of PCROP_RDP option
+ * @param PCROP1AStartAddr [out] Specifies the address where to copied the start address
+ * of the Zone 1A Proprietary code readout protection
+ * @param PCROP1AEndAddr [out] Specifies the address where to copied the end address of
+ * the Zone 1A Proprietary code readout protection
+ * @param PCROP1BStartAddr [out] Specifies the address where to copied the start address
+ * of the Zone 1B Proprietary code readout protection
+ * @param PCROP1BEndAddr [out] Specifies the address where to copied the end address of
+ * the Zone 1B Proprietary code readout protection
+ * @retval None
+ */
+static void FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr,
+ uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr)
+{
+ uint32_t pcrop;
+
+ pcrop = (READ_BIT(FLASH->PCROP1BSR, FLASH_PCROP1BSR_PCROP1B_STRT));
+ *PCROP1BStartAddr = ((pcrop << FLASH_PCROP_GRANULARITY_OFFSET) + FLASH_BASE);
+
+ pcrop = (READ_BIT(FLASH->PCROP1BER, FLASH_PCROP1BER_PCROP1B_END));
+ *PCROP1BEndAddr = ((pcrop << FLASH_PCROP_GRANULARITY_OFFSET) + FLASH_BASE);
+
+ pcrop = (READ_BIT(FLASH->PCROP1ASR, FLASH_PCROP1ASR_PCROP1A_STRT));
+ *PCROP1AStartAddr = ((pcrop << FLASH_PCROP_GRANULARITY_OFFSET) + FLASH_BASE);
+
+ pcrop = (READ_BIT(FLASH->PCROP1AER, FLASH_PCROP1AER_PCROP1A_END));
+ *PCROP1AEndAddr = ((pcrop << FLASH_PCROP_GRANULARITY_OFFSET) + FLASH_BASE);
+
+ *PCROPConfig = (READ_REG(FLASH->PCROP1AER) & FLASH_PCROP1AER_PCROP_RDP);
+}
+
+/**
+ * @brief Return the FLASH IPCC data buffer base address Option Byte value.
+ * @retval Returned value is the IPCC data buffer start address area in SRAM2.
+ */
+static uint32_t FLASH_OB_GetIPCCBufferAddr(void)
+{
+ return (uint32_t)((READ_BIT(FLASH->IPCCBR, FLASH_IPCCBR_IPCCDBA) << 4) + SRAM2A_BASE);
+}
+
+/**
+ * @brief Return the Secure Flash start address, Secure Backup RAM2a start address, Secure non-Backup RAM2b start address and the SecureMode
+ * @param SecureFlashStartAddr Specifies the address where to copied the Secure Flash start address
+ * @param SecureRAM2aStartAddr Specifies the address where to copied the Secure Backup RAM2a start address
+ * @param SecureRAM2bStartAddr Specifies the address where to copied the Secure non-Backup RAM2b start address
+ * @param SecureMode Specifies the address where to copied the Secure Mode.
+ * This return value can be one of the following values:
+ * @arg @ref SYSTEM_IN_SECURE_MODE : Security enabled
+ * @arg @ref SYSTEM_NOT_IN_SECURE_MODE : Security disabled
+ * @retval None
+ */
+static void FLASH_OB_GetSecureMemoryConfig(uint32_t *SecureFlashStartAddr, uint32_t *SecureRAM2aStartAddr,
+ uint32_t *SecureRAM2bStartAddr, uint32_t *SecureMode)
+{
+ uint32_t sfr_reg_val = READ_REG(FLASH->SFR);
+ uint32_t srrvr_reg_val = READ_REG(FLASH->SRRVR);
+
+ /* Get Secure Flash start address */
+ uint32_t user_config = (READ_BIT(sfr_reg_val, FLASH_SFR_SFSA) >> FLASH_SFR_SFSA_Pos);
+
+ *SecureFlashStartAddr = ((user_config * FLASH_PAGE_SIZE) + FLASH_BASE);
+
+ /* Get Secure SRAM2a start address */
+#if defined(FLASH_SRRVR_SBRSA_A)
+ user_config = (READ_BIT(srrvr_reg_val, FLASH_SRRVR_SBRSA_A) >> FLASH_SRRVR_SBRSA_A_Pos);
+#else
+ user_config = (READ_BIT(srrvr_reg_val, FLASH_SRRVR_SBRSA) >> FLASH_SRRVR_SBRSA_Pos);
+#endif /* FLASH_SRRVR_SBRSA_A */
+
+ *SecureRAM2aStartAddr = ((user_config << SRAM_SECURE_PAGE_GRANULARITY_OFFSET) + SRAM2A_BASE);
+
+ /* Get Secure SRAM2b start address */
+#if defined(FLASH_SRRVR_SBRSA_B)
+ user_config = (READ_BIT(srrvr_reg_val, FLASH_SRRVR_SBRSA_B) >> FLASH_SRRVR_SBRSA_B_Pos);
+#else
+ user_config = (READ_BIT(srrvr_reg_val, FLASH_SRRVR_SNBRSA) >> FLASH_SRRVR_SNBRSA_Pos);
+#endif /* FLASH_SRRVR_SBRSA_B */
+
+ *SecureRAM2bStartAddr = ((user_config << SRAM_SECURE_PAGE_GRANULARITY_OFFSET) + SRAM2B_BASE);
+
+ /* Get Secure Area mode */
+ *SecureMode = (READ_BIT(FLASH->OPTR, FLASH_OPTR_ESE));
+}
+
+/**
+ * @brief Return the CPU2 Secure Boot reset vector address and the CPU2 Secure Boot Region
+ * @param C2BootResetVectAddr Specifies the address where to copied the CPU2 Secure Boot reset vector address
+ * @param C2BootResetRegion Specifies the Secure Boot reset memory region
+ * @retval None
+ */
+static void FLASH_OB_GetC2BootResetConfig(uint32_t *C2BootResetVectAddr, uint32_t *C2BootResetRegion)
+{
+ *C2BootResetRegion = (READ_BIT(FLASH->SRRVR, FLASH_SRRVR_C2OPT));
+
+ if (*C2BootResetRegion == OB_C2_BOOT_FROM_FLASH)
+ {
+ *C2BootResetVectAddr = (uint32_t)((READ_BIT(FLASH->SRRVR, FLASH_SRRVR_SBRV) << 2) + FLASH_BASE);
+ }
+ else
+ {
+ *C2BootResetVectAddr = (uint32_t)((READ_BIT(FLASH->SRRVR, FLASH_SRRVR_SBRV) << 2) + SRAM1_BASE);
+ }
+}
+
+/**
+ * @brief Proceed the OB Write Operation.
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_ProceedWriteOperation(void)
+{
+ HAL_StatusTypeDef status;
+
+ /* Verify that next operation can be proceed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+
+ if (status == HAL_OK)
+ {
+ /* Set OPTSTRT Bit */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_gpio.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_gpio.c
new file mode 100644
index 0000000..564acc3
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_gpio.c
@@ -0,0 +1,551 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_gpio.c
+ * @author MCD Application Team
+ * @brief GPIO HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the General Purpose Input/Output (GPIO) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### GPIO Peripheral features #####
+ ==============================================================================
+ [..]
+ (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually
+ configured by software in several modes:
+ (++) Input mode
+ (++) Analog mode
+ (++) Output mode
+ (++) Alternate function mode
+ (++) External interrupt/event lines
+
+ (+) During and just after reset, the alternate functions and external interrupt
+ lines are not active and the I/O ports are configured in input floating mode.
+
+ (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be
+ activated or not.
+
+ (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull
+ type and the IO speed can be selected depending on the VDD value.
+
+ (+) The microcontroller IO pins are connected to onboard peripherals/modules through a
+ multiplexer that allows only one peripheral alternate function (AF) connected
+ to an IO pin at a time. In this way, there can be no conflict between peripherals
+ sharing the same IO pin.
+
+ (+) All ports have external interrupt/event capability. To use external interrupt
+ lines, the port must be configured in input mode. All available GPIO pins are
+ connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
+
+ (+) The external interrupt/event controller consists of up to 28 edge detectors
+ (16 lines are connected to GPIO) for generating event/interrupt requests (each
+ input line can be independently configured to select the type (interrupt or event)
+ and the corresponding trigger event (rising or falling or both). Each line can
+ also be masked independently.
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
+
+ (#) Configure the GPIO pin(s) using HAL_GPIO_Init().
+ (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
+ (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
+ structure.
+ (++) In case of Output or alternate function mode selection: the speed is
+ configured through "Speed" member from GPIO_InitTypeDef structure.
+ (++) In alternate mode is selection, the alternate function connected to the IO
+ is configured through "Alternate" member from GPIO_InitTypeDef structure.
+ (++) Analog mode is required when a pin is to be used as ADC channel
+ or DAC output.
+ (++) In case of external interrupt/event selection the "Mode" member from
+ GPIO_InitTypeDef structure select the type (interrupt or event) and
+ the corresponding trigger event (rising or falling or both).
+
+ (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
+ mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
+ HAL_NVIC_EnableIRQ().
+
+ (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
+
+ (#) To set/reset the level of a pin configured in output mode use
+ HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
+
+ (#) To set the level of several pins and reset level of several other pins in
+ same cycle, use HAL_GPIO_WriteMultipleStatePin().
+
+ (#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
+
+ (#) During and just after reset, the alternate functions are not
+ active and the GPIO pins are configured in input floating mode (except JTAG
+ pins).
+
+ (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
+ (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
+ priority over the GPIO function.
+
+ (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
+ general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
+ The HSE has priority over the GPIO function.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup GPIO
+ * @{
+ */
+/** MISRA C:2012 deviation rule has been granted for following rules:
+ * Rule-12.2 - Medium: RHS argument is in interval [0,INF] which is out of
+ * range of the shift operator in following API :
+ * HAL_GPIO_Init
+ * HAL_GPIO_DeInit
+ */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines ------------------------------------------------------------*/
+/** @addtogroup GPIO_Private_Constants GPIO Private Constants
+ * @{
+ */
+#define GPIO_NUMBER (16u)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup GPIO_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup GPIO_Exported_Functions_Group1
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
+ * @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32WBxx family
+ * @param GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
+ * the configuration information for the specified GPIO peripheral.
+ * @retval None
+ */
+void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
+{
+ uint32_t position = 0x00u;
+ uint32_t iocurrent;
+ uint32_t temp;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
+ assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
+ assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
+
+ /* Configure the port pins */
+ while (((GPIO_Init->Pin) >> position) != 0x00u)
+ {
+ /* Get current io position */
+ iocurrent = (GPIO_Init->Pin) & (1uL << position);
+
+ if (iocurrent != 0x00u)
+ {
+ /*--------------------- GPIO Mode Configuration ------------------------*/
+ /* In case of Output or Alternate function mode selection */
+ if (((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) || ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF))
+ {
+ /* Check the Speed parameter */
+ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
+ /* Configure the IO Speed */
+ temp = GPIOx->OSPEEDR;
+ temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
+ temp |= (GPIO_Init->Speed << (position * 2u));
+ GPIOx->OSPEEDR = temp;
+
+ /* Configure the IO Output Type */
+ temp = GPIOx->OTYPER;
+ temp &= ~(GPIO_OTYPER_OT0 << position) ;
+ temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
+ GPIOx->OTYPER = temp;
+ }
+
+ /* Activate the Pull-up or Pull down resistor for the current IO */
+ if ((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
+ {
+ temp = GPIOx->PUPDR;
+ temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
+ temp |= ((GPIO_Init->Pull) << (position * 2U));
+ GPIOx->PUPDR = temp;
+ }
+
+ /* In case of Alternate function mode selection */
+ if ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
+ {
+ /* Check the Alternate function parameters */
+ assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
+
+ /* Configure Alternate function mapped with the current IO */
+ temp = GPIOx->AFR[position >> 3u];
+ temp &= ~(0xFu << ((position & 0x07u) * 4u));
+ temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));
+ GPIOx->AFR[position >> 3u] = temp;
+ }
+
+ /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
+ temp = GPIOx->MODER;
+ temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
+ temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
+ GPIOx->MODER = temp;
+
+ /*--------------------- EXTI Mode Configuration ------------------------*/
+ /* Configure the External Interrupt or event for the current IO */
+ if ((GPIO_Init->Mode & EXTI_MODE) != 0x00u)
+ {
+ temp = SYSCFG->EXTICR[position >> 2u];
+ temp &= ~(0x0FuL << (4u * (position & 0x03u)));
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
+ SYSCFG->EXTICR[position >> 2u] = temp;
+
+ /* Clear Rising Falling edge configuration */
+ temp = EXTI->RTSR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & TRIGGER_RISING) != 0x00u)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->RTSR1 = temp;
+
+ temp = EXTI->FTSR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00u)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->FTSR1 = temp;
+
+ /* Clear EXTI line configuration */
+ temp = EXTI->IMR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & EXTI_IT) != 0x00u)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->IMR1 = temp;
+
+ temp = EXTI->EMR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & EXTI_EVT) != 0x00u)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->EMR1 = temp;
+ }
+ }
+
+ position++;
+ }
+}
+
+/**
+ * @brief De-initialize the GPIOx peripheral registers to their default reset values.
+ * @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32WBxx family
+ * @param GPIO_Pin specifies the port bit to be written.
+ * This parameter can be one of GPIO_PIN_x where x can be (0..15).
+ * @retval None
+ */
+void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
+{
+ uint32_t position = 0x00u;
+ uint32_t iocurrent;
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* Configure the port pins */
+ while ((GPIO_Pin >> position) != 0x00u)
+ {
+ /* Get current io position */
+ iocurrent = (GPIO_Pin) & (1uL << position);
+
+ if (iocurrent != 0x00u)
+ {
+ /*------------------------- EXTI Mode Configuration --------------------*/
+ /* Clear the External Interrupt or Event for the current IO */
+
+ tmp = SYSCFG->EXTICR[position >> 2u];
+ tmp &= (0x0FUL << (4u * (position & 0x03u)));
+ if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u))))
+ {
+ /* Clear EXTI line configuration */
+ EXTI->IMR1 &= ~(iocurrent);
+ EXTI->EMR1 &= ~(iocurrent);
+
+ /* Clear Rising Falling edge configuration */
+ EXTI->RTSR1 &= ~(iocurrent);
+ EXTI->FTSR1 &= ~(iocurrent);
+
+ tmp = 0x0FuL << (4u * (position & 0x03u));
+ SYSCFG->EXTICR[position >> 2u] &= ~tmp;
+ }
+
+ /*------------------------- GPIO Mode Configuration --------------------*/
+ /* Configure IO in Analog Mode */
+ GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2u));
+
+ /* Configure the default Alternate Function in current IO */
+ GPIOx->AFR[position >> 3u] &= ~(0xFu << ((position & 0x07u) * 4u)) ;
+
+ /* Deactivate the Pull-up and Pull-down resistor for the current IO */
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
+
+ /* Configure the default value IO Output Type */
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ;
+
+ /* Configure the default value for IO Speed */
+ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
+ }
+
+ position++;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup GPIO_Exported_Functions_Group2
+ * @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Read the specified input port pin.
+ * @param GPIOx where x can be (A..F) to select the GPIO peripheral for STM32WBxx family
+ * @param GPIO_Pin specifies the port bit to read.
+ * This parameter can be GPIO_PIN_x where x can be (0..15).
+ * @retval The input port pin value.
+ */
+GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
+{
+ GPIO_PinState bitstatus;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ if ((GPIOx->IDR & GPIO_Pin) != 0x00u)
+ {
+ bitstatus = GPIO_PIN_SET;
+ }
+ else
+ {
+ bitstatus = GPIO_PIN_RESET;
+ }
+ return bitstatus;
+}
+
+/**
+ * @brief Set or clear the selected data port bit.
+ * @note This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
+ * accesses. In this way, there is no risk of an IRQ occurring between
+ * the read and the modify access.
+ * @param GPIOx where x can be (A..F) to select the GPIO peripheral for STM32WBxx family
+ * @param GPIO_Pin specifies the port bit to be written.
+ * This parameter can be one of GPIO_PIN_x where x can be (0..15).
+ * @param PinState specifies the value to be written to the selected bit.
+ * This parameter can be one of the GPIO_PinState enum values:
+ * @arg GPIO_PIN_RESET: to clear the port pin
+ * @arg GPIO_PIN_SET: to set the port pin
+ * @retval None
+ */
+void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+ assert_param(IS_GPIO_PIN_ACTION(PinState));
+
+ if (PinState != GPIO_PIN_RESET)
+ {
+ GPIOx->BSRR = (uint32_t)GPIO_Pin;
+ }
+ else
+ {
+ GPIOx->BRR = (uint32_t)GPIO_Pin;
+ }
+}
+
+/**
+ * @brief Set and clear several pins of a dedicated port in same cycle.
+ * @note This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
+ * accesses.
+ * @param GPIOx where x can be (A..F) to select the GPIO peripheral for STM32WLxx family
+ * @param PinReset specifies the port bits to be reset
+ * This parameter can be any combination of GPIO_PIN_x where x can be (0..15) or zero.
+ * @param PinSet specifies the port bits to be set
+ * This parameter can be any combination of GPIO_PIN_x where x can be (0..15) or zero.
+ * @note Both PinReset and PinSet combinations shall not get any common bit, else
+ * assert would be triggered.
+ * @note At least one of the two parameters used to set or reset shall be different from zero.
+ * @retval None
+ */
+void HAL_GPIO_WriteMultipleStatePin(GPIO_TypeDef *GPIOx, uint16_t PinReset, uint16_t PinSet)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ /* Make sure at least one parameter is different from zero and that there is no common pin */
+ assert_param(IS_GPIO_PIN((uint32_t)PinReset | (uint32_t)PinSet));
+ assert_param(IS_GPIO_COMMON_PIN(PinReset, PinSet));
+
+ tmp = (((uint32_t)PinReset << 16) | PinSet);
+ GPIOx->BSRR = tmp;
+}
+
+/**
+ * @brief Toggle the specified GPIO pin.
+ * @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32WBxx family
+ * @param GPIO_Pin specifies the pin to be toggled.
+ * @retval None
+ */
+void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
+{
+ uint32_t odr;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* get current Output Data Register value */
+ odr = GPIOx->ODR;
+
+ /* Set selected pins that were at low level, and reset ones that were high */
+ GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
+}
+
+/**
+ * @brief Lock GPIO Pins configuration registers.
+ * @note The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
+ * GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
+ * @note The configuration of the locked GPIO pins can no longer be modified
+ * until the next reset.
+ * @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32WBxx family
+ * @param GPIO_Pin specifies the port bits to be locked.
+ * This parameter can be any combination of GPIO_PIN_x where x can be (0..15).
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
+{
+ __IO uint32_t tmp = GPIO_LCKR_LCKK;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* Apply lock key write sequence */
+ tmp |= GPIO_Pin;
+ /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
+ GPIOx->LCKR = tmp;
+ /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
+ GPIOx->LCKR = GPIO_Pin;
+ /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
+ GPIOx->LCKR = tmp;
+ /* Read LCKK register. This read is mandatory to complete key lock sequence */
+ tmp = GPIOx->LCKR;
+
+ /* read again in order to confirm lock is active */
+ if ((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00u)
+ {
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Handle EXTI interrupt request.
+ * @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
+ * @retval None
+ */
+void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
+{
+ /* EXTI line interrupt detected */
+ if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
+ {
+ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
+ HAL_GPIO_EXTI_Callback(GPIO_Pin);
+ }
+}
+
+/**
+ * @brief EXTI line detection callback.
+ * @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
+ * @retval None
+ */
+__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(GPIO_Pin);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_GPIO_EXTI_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_GPIO_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_hsem.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_hsem.c
new file mode 100644
index 0000000..7f6883f
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_hsem.c
@@ -0,0 +1,369 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_hsem.c
+ * @author MCD Application Team
+ * @brief HSEM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the semaphore peripheral:
+ * + Semaphore Take function (2-Step Procedure) , non blocking
+ * + Semaphore FastTake function (1-Step Procedure) , non blocking
+ * + Semaphore Status check
+ * + Semaphore Clear Key Set and Get
+ * + Release and release all functions
+ * + Semaphore notification enabling and disabling and callnack functions
+ * + IRQ handler management
+ *
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#)Take a semaphore In 2-Step mode Using function HAL_HSEM_Take. This function takes as parameters :
+ (++) the semaphore ID from 0 to 31
+ (++) the process ID from 0 to 255
+ (#) Fast Take semaphore In 1-Step mode Using function HAL_HSEM_FastTake. This function takes as parameter :
+ (++) the semaphore ID from 0_ID to 31. Note that the process ID value is implicitly assumed as zero
+ (#) Check if a semaphore is Taken using function HAL_HSEM_IsSemTaken. This function takes as parameter :
+ (++) the semaphore ID from 0_ID to 31
+ (++) It returns 1 if the given semaphore is taken otherwise (Free) zero
+ (#)Release a semaphore using function with HAL_HSEM_Release. This function takes as parameters :
+ (++) the semaphore ID from 0 to 31
+ (++) the process ID from 0 to 255:
+ (++) Note: If ProcessID and MasterID match, semaphore is freed, and an interrupt
+ may be generated when enabled (notification activated). If ProcessID or MasterID does not match,
+ semaphore remains taken (locked)
+
+ (#)Release all semaphores at once taken by a given Master using function HAL_HSEM_Release_All
+ This function takes as parameters :
+ (++) the Release Key (value from 0 to 0xFFFF) can be Set or Get respectively by
+ HAL_HSEM_SetClearKey() or HAL_HSEM_GetClearKey functions
+ (++) the Master ID:
+ (++) Note: If the Key and MasterID match, all semaphores taken by the given CPU that corresponds
+ to MasterID will be freed, and an interrupt may be generated when enabled (notification activated). If the
+ Key or the MasterID doesn't match, semaphores remains taken (locked)
+
+ (#)Semaphores Release all key functions:
+ (++) HAL_HSEM_SetClearKey() to set semaphore release all Key
+ (++) HAL_HSEM_GetClearKey() to get release all Key
+ (#)Semaphores notification functions :
+ (++) HAL_HSEM_ActivateNotification to activate a notification callback on
+ a given semaphores Mask (bitfield). When one or more semaphores defined by the mask are released
+ the callback HAL_HSEM_FreeCallback will be asserted giving as parameters a mask of the released
+ semaphores (bitfield).
+
+ (++) HAL_HSEM_DeactivateNotification to deactivate the notification of a given semaphores Mask (bitfield).
+ (++) See the description of the macro __HAL_HSEM_SEMID_TO_MASK to check how to calculate a semaphore mask
+ Used by the notification functions
+ *** HSEM HAL driver macros list ***
+ =============================================
+ [..] Below the list of most used macros in HSEM HAL driver.
+
+ (+) __HAL_HSEM_SEMID_TO_MASK: Helper macro to convert a Semaphore ID to a Mask.
+ [..] Example of use :
+ [..] mask = __HAL_HSEM_SEMID_TO_MASK(8) | __HAL_HSEM_SEMID_TO_MASK(21) | __HAL_HSEM_SEMID_TO_MASK(25).
+ [..] All next macros take as parameter a semaphore Mask (bitfiled) that can be constructed using __HAL_HSEM_SEMID_TO_MASK as the above example.
+ (+) __HAL_HSEM_ENABLE_IT: Enable the specified semaphores Mask interrupts.
+ (+) __HAL_HSEM_DISABLE_IT: Disable the specified semaphores Mask interrupts.
+ (+) __HAL_HSEM_GET_IT: Checks whether the specified semaphore interrupt has occurred or not.
+ (+) __HAL_HSEM_GET_FLAG: Get the semaphores status release flags.
+ (+) __HAL_HSEM_CLEAR_FLAG: Clear the semaphores status release flags.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup HSEM HSEM
+ * @brief HSEM HAL module driver
+ * @{
+ */
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#if defined(DUAL_CORE)
+/** @defgroup HSEM_Private_Constants HSEM Private Constants
+ * @{
+ */
+
+#ifndef HSEM_R_MASTERID
+#define HSEM_R_MASTERID HSEM_R_COREID
+#endif
+
+#ifndef HSEM_RLR_MASTERID
+#define HSEM_RLR_MASTERID HSEM_RLR_COREID
+#endif
+
+#ifndef HSEM_CR_MASTERID
+#define HSEM_CR_MASTERID HSEM_CR_COREID
+#endif
+
+/**
+ * @}
+ */
+#endif /* DUAL_CORE */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup HSEM_Exported_Functions HSEM Exported Functions
+ * @{
+ */
+
+/** @defgroup HSEM_Exported_Functions_Group1 Take and Release functions
+ * @brief HSEM Take and Release functions
+ *
+@verbatim
+ ==============================================================================
+ ##### HSEM Take and Release functions #####
+ ==============================================================================
+[..] This section provides functions allowing to:
+ (+) Take a semaphore with 2 Step method
+ (+) Fast Take a semaphore with 1 Step method
+ (+) Check semaphore state Taken or not
+ (+) Release a semaphore
+ (+) Release all semaphore at once
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Take a semaphore in 2 Step mode.
+ * @param SemID: semaphore ID from 0 to 31
+ * @param ProcessID: Process ID from 0 to 255
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HSEM_Take(uint32_t SemID, uint32_t ProcessID)
+{
+ /* Check the parameters */
+ assert_param(IS_HSEM_SEMID(SemID));
+ assert_param(IS_HSEM_PROCESSID(ProcessID));
+
+ /* First step write R register with MasterID, processID and take bit=1*/
+ HSEM->R[SemID] = (ProcessID | HSEM_CR_COREID_CURRENT | HSEM_R_LOCK);
+
+ /* second step : read the R register . Take achieved if MasterID and processID match and take bit set to 1 */
+ if (HSEM->R[SemID] == (ProcessID | HSEM_CR_COREID_CURRENT | HSEM_R_LOCK))
+ {
+ /*take success when MasterID and ProcessID match and take bit set*/
+ return HAL_OK;
+ }
+
+ /* Semaphore take fails*/
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Fast Take a semaphore with 1 Step mode.
+ * @param SemID: semaphore ID from 0 to 31
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HSEM_FastTake(uint32_t SemID)
+{
+ /* Check the parameters */
+ assert_param(IS_HSEM_SEMID(SemID));
+
+ /* Read the RLR register to take the semaphore */
+ if (HSEM->RLR[SemID] == (HSEM_CR_COREID_CURRENT | HSEM_RLR_LOCK))
+ {
+ /*take success when MasterID match and take bit set*/
+ return HAL_OK;
+ }
+
+ /* Semaphore take fails */
+ return HAL_ERROR;
+}
+/**
+ * @brief Check semaphore state Taken or not.
+ * @param SemID: semaphore ID
+ * @retval HAL HSEM state
+ */
+uint32_t HAL_HSEM_IsSemTaken(uint32_t SemID)
+{
+ return (((HSEM->R[SemID] & HSEM_R_LOCK) != 0U) ? 1UL : 0UL);
+}
+
+
+/**
+ * @brief Release a semaphore.
+ * @param SemID: semaphore ID from 0 to 31
+ * @param ProcessID: Process ID from 0 to 255
+ * @retval None
+ */
+void HAL_HSEM_Release(uint32_t SemID, uint32_t ProcessID)
+{
+ /* Check the parameters */
+ assert_param(IS_HSEM_SEMID(SemID));
+ assert_param(IS_HSEM_PROCESSID(ProcessID));
+
+ /* Clear the semaphore by writing to the R register : the MasterID , the processID and take bit = 0 */
+ HSEM->R[SemID] = (ProcessID | HSEM_CR_COREID_CURRENT);
+
+}
+
+/**
+ * @brief Release All semaphore used by a given Master .
+ * @param Key: Semaphore Key , value from 0 to 0xFFFF
+ * @param CoreID: CoreID of the CPU that is using semaphores to be released
+ * @retval None
+ */
+void HAL_HSEM_ReleaseAll(uint32_t Key, uint32_t CoreID)
+{
+ assert_param(IS_HSEM_KEY(Key));
+ assert_param(IS_HSEM_COREID(CoreID));
+
+ HSEM->CR = ((Key << HSEM_CR_KEY_Pos) | (CoreID << HSEM_CR_COREID_Pos));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HSEM_Exported_Functions_Group2 HSEM Set and Get Key functions
+ * @brief HSEM Set and Get Key functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### HSEM Set and Get Key functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Set semaphore Key
+ (+) Get semaphore Key
+@endverbatim
+
+ * @{
+ */
+
+/**
+ * @brief Set semaphore Key .
+ * @param Key: Semaphore Key , value from 0 to 0xFFFF
+ * @retval None
+ */
+void HAL_HSEM_SetClearKey(uint32_t Key)
+{
+ assert_param(IS_HSEM_KEY(Key));
+
+ MODIFY_REG(HSEM->KEYR, HSEM_KEYR_KEY, (Key << HSEM_KEYR_KEY_Pos));
+
+}
+
+/**
+ * @brief Get semaphore Key .
+ * @retval Semaphore Key , value from 0 to 0xFFFF
+ */
+uint32_t HAL_HSEM_GetClearKey(void)
+{
+ return (HSEM->KEYR >> HSEM_KEYR_KEY_Pos);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HSEM_Exported_Functions_Group3 HSEM IRQ handler management
+ * @brief HSEM Notification functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### HSEM IRQ handler management and Notification functions #####
+ ==============================================================================
+[..] This section provides HSEM IRQ handler and Notification function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Activate Semaphore release Notification for a given Semaphores Mask .
+ * @param SemMask: Mask of Released semaphores
+ * @retval Semaphore Key
+ */
+void HAL_HSEM_ActivateNotification(uint32_t SemMask)
+{
+ HSEM_COMMON->IER |= SemMask;
+}
+
+/**
+ * @brief Deactivate Semaphore release Notification for a given Semaphores Mask .
+ * @param SemMask: Mask of Released semaphores
+ * @retval Semaphore Key
+ */
+void HAL_HSEM_DeactivateNotification(uint32_t SemMask)
+{
+ HSEM_COMMON->IER &= ~SemMask;
+}
+
+/**
+ * @brief This function handles HSEM interrupt request
+ * @retval None
+ */
+void HAL_HSEM_IRQHandler(void)
+{
+ uint32_t statusreg;
+ /* Get the list of masked freed semaphores*/
+ statusreg = HSEM_COMMON->MISR;
+
+ /*Disable Interrupts*/
+ HSEM_COMMON->IER &= ~((uint32_t)statusreg);
+
+ /*Clear Flags*/
+ HSEM_COMMON->ICR = ((uint32_t)statusreg);
+
+ /* Call FreeCallback */
+ HAL_HSEM_FreeCallback(statusreg);
+}
+
+/**
+ * @brief Semaphore Released Callback.
+ * @param SemMask: Mask of Released semaphores
+ * @retval None
+ */
+__weak void HAL_HSEM_FreeCallback(uint32_t SemMask)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(SemMask);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HSEM_FreeCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_HSEM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c.c
new file mode 100644
index 0000000..91993d6
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c.c
@@ -0,0 +1,7561 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_i2c.c
+ * @author MCD Application Team
+ * @brief I2C HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Inter Integrated Circuit (I2C) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The I2C HAL driver can be used as follows:
+
+ (#) Declare a I2C_HandleTypeDef handle structure, for example:
+ I2C_HandleTypeDef hi2c;
+
+ (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API:
+ (##) Enable the I2Cx interface clock
+ (##) I2C pins configuration
+ (+++) Enable the clock for the I2C GPIOs
+ (+++) Configure I2C pins as alternate function open-drain
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the I2Cx interrupt priority
+ (+++) Enable the NVIC I2C IRQ Channel
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare a DMA_HandleTypeDef handle structure for
+ the transmit or receive channel
+ (+++) Enable the DMAx interface clock using
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx channel
+ (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
+ the DMA Tx or Rx channel
+
+ (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode,
+ Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure.
+
+ (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware
+ (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API.
+
+ (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady()
+
+ (#) For I2C IO and IO MEM operations, three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit()
+ (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive()
+ (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit()
+ (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive()
+
+ *** Polling mode IO MEM operation ***
+ =====================================
+ [..]
+ (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write()
+ (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read()
+
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT()
+ (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Receive_IT()
+ (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Transmit_IT()
+ (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Receive_IT()
+ (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (+) Abort a master or memory I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_AbortCpltCallback()
+ (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro.
+ This action will inform Master to generate a Stop condition to discard the communication.
+
+
+ *** Interrupt mode or DMA mode IO sequential operation ***
+ ==========================================================
+ [..]
+ (@) These interfaces allow to manage a sequential transfer with a repeated start condition
+ when a direction change during transfer
+ [..]
+ (+) A specific option field manage the different steps of a sequential transfer
+ (+) Option field values are defined through I2C_XFEROPTIONS and are listed below:
+ (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functional is same as associated interfaces in
+ no sequential mode
+ (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address
+ and data to transfer without a final stop condition
+ (++) I2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with
+ start condition, address and data to transfer without a final stop condition,
+ an then permit a call the same master sequential interface several times
+ (like HAL_I2C_Master_Seq_Transmit_IT() then HAL_I2C_Master_Seq_Transmit_IT()
+ or HAL_I2C_Master_Seq_Transmit_DMA() then HAL_I2C_Master_Seq_Transmit_DMA())
+ (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address
+ and with new data to transfer if the direction change or manage only the new data to
+ transfer
+ if no direction change and without a final stop condition in both cases
+ (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address
+ and with new data to transfer if the direction change or manage only the new data to
+ transfer
+ if no direction change and with a final stop condition in both cases
+ (++) I2C_LAST_FRAME_NO_STOP: Sequential usage (Master only), this option allow to manage a restart condition
+ after several call of the same master sequential interface several times
+ (link with option I2C_FIRST_AND_NEXT_FRAME).
+ Usage can, transfer several bytes one by one using
+ HAL_I2C_Master_Seq_Transmit_IT
+ or HAL_I2C_Master_Seq_Receive_IT
+ or HAL_I2C_Master_Seq_Transmit_DMA
+ or HAL_I2C_Master_Seq_Receive_DMA
+ with option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME.
+ Then usage of this option I2C_LAST_FRAME_NO_STOP at the last Transmit or
+ Receive sequence permit to call the opposite interface Receive or Transmit
+ without stopping the communication and so generate a restart condition.
+ (++) I2C_OTHER_FRAME: Sequential usage (Master only), this option allow to manage a restart condition after
+ each call of the same master sequential
+ interface.
+ Usage can, transfer several bytes one by one with a restart with slave address between
+ each bytes using
+ HAL_I2C_Master_Seq_Transmit_IT
+ or HAL_I2C_Master_Seq_Receive_IT
+ or HAL_I2C_Master_Seq_Transmit_DMA
+ or HAL_I2C_Master_Seq_Receive_DMA
+ with option I2C_FIRST_FRAME then I2C_OTHER_FRAME.
+ Then usage of this option I2C_OTHER_AND_LAST_FRAME at the last frame to help automatic
+ generation of STOP condition.
+
+ (+) Different sequential I2C interfaces are listed below:
+ (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Master_Seq_Transmit_IT() or using HAL_I2C_Master_Seq_Transmit_DMA()
+ (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and
+ users can add their own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Master_Seq_Receive_IT() or using HAL_I2C_Master_Seq_Receive_DMA()
+ (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (++) Abort a master or memory IT or DMA I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_AbortCpltCallback()
+ (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT()
+ HAL_I2C_DisableListen_IT()
+ (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and users can
+ add their own code to check the Address Match Code and the transmission direction request by master
+ (Write/Read).
+ (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ListenCpltCallback()
+ (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Slave_Seq_Transmit_IT() or using HAL_I2C_Slave_Seq_Transmit_DMA()
+ (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and
+ users can add their own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Slave_Seq_Receive_IT() or using HAL_I2C_Slave_Seq_Receive_DMA()
+ (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (++) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro.
+ This action will inform Master to generate a Stop condition to discard the communication.
+
+ *** Interrupt mode IO MEM operation ***
+ =======================================
+ [..]
+ (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using
+ HAL_I2C_Mem_Write_IT()
+ (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using
+ HAL_I2C_Mem_Read_IT()
+ (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Master_Transmit_DMA()
+ (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Master_Receive_DMA()
+ (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Slave_Transmit_DMA()
+ (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Slave_Receive_DMA()
+ (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (+) Abort a master or memory I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_AbortCpltCallback()
+ (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro.
+ This action will inform Master to generate a Stop condition to discard the communication.
+
+ *** DMA mode IO MEM operation ***
+ =================================
+ [..]
+ (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using
+ HAL_I2C_Mem_Write_DMA()
+ (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using
+ HAL_I2C_Mem_Read_DMA()
+ (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+
+ *** I2C HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in I2C HAL driver.
+
+ (+) __HAL_I2C_ENABLE: Enable the I2C peripheral
+ (+) __HAL_I2C_DISABLE: Disable the I2C peripheral
+ (+) __HAL_I2C_GENERATE_NACK: Generate a Non-Acknowledge I2C peripheral in Slave mode
+ (+) __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not
+ (+) __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag
+ (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt
+ (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation flag USE_HAL_I2C_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_I2C_RegisterCallback() or HAL_I2C_RegisterAddrCallback()
+ to register an interrupt callback.
+ [..]
+ Function HAL_I2C_RegisterCallback() allows to register following callbacks:
+ (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
+ (+) MasterRxCpltCallback : callback for Master reception end of transfer.
+ (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer.
+ (+) SlaveRxCpltCallback : callback for Slave reception end of transfer.
+ (+) ListenCpltCallback : callback for end of listen mode.
+ (+) MemTxCpltCallback : callback for Memory transmission end of transfer.
+ (+) MemRxCpltCallback : callback for Memory reception end of transfer.
+ (+) ErrorCallback : callback for error detection.
+ (+) AbortCpltCallback : callback for abort completion process.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+ [..]
+ For specific callback AddrCallback use dedicated register callbacks : HAL_I2C_RegisterAddrCallback().
+ [..]
+ Use function HAL_I2C_UnRegisterCallback to reset a callback to the default
+ weak function.
+ HAL_I2C_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
+ (+) MasterRxCpltCallback : callback for Master reception end of transfer.
+ (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer.
+ (+) SlaveRxCpltCallback : callback for Slave reception end of transfer.
+ (+) ListenCpltCallback : callback for end of listen mode.
+ (+) MemTxCpltCallback : callback for Memory transmission end of transfer.
+ (+) MemRxCpltCallback : callback for Memory reception end of transfer.
+ (+) ErrorCallback : callback for error detection.
+ (+) AbortCpltCallback : callback for abort completion process.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+ [..]
+ For callback AddrCallback use dedicated register callbacks : HAL_I2C_UnRegisterAddrCallback().
+ [..]
+ By default, after the HAL_I2C_Init() and when the state is HAL_I2C_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_I2C_MasterTxCpltCallback(), HAL_I2C_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the HAL_I2C_Init()/ HAL_I2C_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the HAL_I2C_Init()/ HAL_I2C_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+ Callbacks can be registered/unregistered in HAL_I2C_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_I2C_STATE_READY or HAL_I2C_STATE_RESET state,
+ thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
+ Then, the user first registers the MspInit/MspDeInit user callbacks
+ using HAL_I2C_RegisterCallback() before calling HAL_I2C_DeInit()
+ or HAL_I2C_Init() function.
+ [..]
+ When the compilation flag USE_HAL_I2C_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all callbacks
+ are set to the corresponding weak functions.
+
+ [..]
+ (@) You can refer to the I2C HAL driver header file for more useful macros
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2C I2C
+ * @brief I2C HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup I2C_Private_Define I2C Private Define
+ * @{
+ */
+#define TIMING_CLEAR_MASK (0xF0FFFFFFU) /*!< I2C TIMING clear register Mask */
+#define I2C_TIMEOUT_ADDR (10000U) /*!< 10 s */
+#define I2C_TIMEOUT_BUSY (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_DIR (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_RXNE (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_STOPF (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_TC (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_TCR (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_TXIS (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_FLAG (25U) /*!< 25 ms */
+
+#define MAX_NBYTE_SIZE 255U
+#define SLAVE_ADDR_SHIFT 7U
+#define SLAVE_ADDR_MSK 0x06U
+
+/* Private define for @ref PreviousState usage */
+#define I2C_STATE_MSK ((uint32_t)((uint32_t)((uint32_t)HAL_I2C_STATE_BUSY_TX | \
+ (uint32_t)HAL_I2C_STATE_BUSY_RX) & \
+ (uint32_t)(~((uint32_t)HAL_I2C_STATE_READY))))
+/*!< Mask State define, keep only RX and TX bits */
+#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE))
+/*!< Default Value */
+#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MASTER))
+/*!< Master Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MASTER))
+/*!< Master Busy RX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_SLAVE))
+/*!< Slave Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_SLAVE))
+/*!< Slave Busy RX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MEM_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MEM))
+/*!< Memory Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MEM_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MEM))
+/*!< Memory Busy RX, combinaison of State LSB and Mode enum */
+
+
+/* Private define to centralize the enable/disable of Interrupts */
+#define I2C_XFER_TX_IT (uint16_t)(0x0001U) /*!< Bit field can be combinated with
+ @ref I2C_XFER_LISTEN_IT */
+#define I2C_XFER_RX_IT (uint16_t)(0x0002U) /*!< Bit field can be combinated with
+ @ref I2C_XFER_LISTEN_IT */
+#define I2C_XFER_LISTEN_IT (uint16_t)(0x8000U) /*!< Bit field can be combinated with @ref I2C_XFER_TX_IT
+ and @ref I2C_XFER_RX_IT */
+
+#define I2C_XFER_ERROR_IT (uint16_t)(0x0010U) /*!< Bit definition to manage addition of global Error
+ and NACK treatment */
+#define I2C_XFER_CPLT_IT (uint16_t)(0x0020U) /*!< Bit definition to manage only STOP evenement */
+#define I2C_XFER_RELOAD_IT (uint16_t)(0x0040U) /*!< Bit definition to manage only Reload of NBYTE */
+
+/* Private define Sequential Transfer Options default/reset value */
+#define I2C_NO_OPTION_FRAME (0xFFFF0000U)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup I2C_Private_Macro
+ * @{
+ */
+#if defined(HAL_DMA_MODULE_ENABLED)
+/* Macro to get remaining data to transfer on DMA side */
+#define I2C_GET_DMA_REMAIN_DATA(__HANDLE__) __HAL_DMA_GET_COUNTER(__HANDLE__)
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup I2C_Private_Functions I2C Private Functions
+ * @{
+ */
+#if defined(HAL_DMA_MODULE_ENABLED)
+/* Private functions to handle DMA transfer */
+static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAError(DMA_HandleTypeDef *hdma);
+static void I2C_DMAAbort(DMA_HandleTypeDef *hdma);
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/* Private functions to handle IT transfer */
+static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITMasterSeqCplt(I2C_HandleTypeDef *hi2c);
+static void I2C_ITSlaveSeqCplt(I2C_HandleTypeDef *hi2c);
+static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode);
+
+/* Private functions to handle IT transfer */
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart);
+
+/* Private functions for I2C transfer IRQ handler */
+static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Mem_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+#if defined(HAL_DMA_MODULE_ENABLED)
+static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Mem_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/* Private functions to handle flags during polling transfer */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status,
+ uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_IsErrorOccurred(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+
+/* Private functions to centralize the enable/disable of Interrupts */
+static void I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest);
+static void I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest);
+
+/* Private function to treat different error callback */
+static void I2C_TreatErrorCallback(I2C_HandleTypeDef *hi2c);
+
+/* Private function to flush TXDR register */
+static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c);
+
+/* Private function to handle start, restart or stop a transfer */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
+ uint32_t Request);
+
+/* Private function to Convert Specific options */
+static void I2C_ConvertOtherXferOptions(I2C_HandleTypeDef *hi2c);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup I2C_Exported_Functions I2C Exported Functions
+ * @{
+ */
+
+/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ deinitialize the I2Cx peripheral:
+
+ (+) User must Implement HAL_I2C_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_I2C_Init() to configure the selected device with
+ the selected configuration:
+ (++) Clock Timing
+ (++) Own Address 1
+ (++) Addressing mode (Master, Slave)
+ (++) Dual Addressing mode
+ (++) Own Address 2
+ (++) Own Address 2 Mask
+ (++) General call mode
+ (++) Nostretch mode
+
+ (+) Call the function HAL_I2C_DeInit() to restore the default configuration
+ of the selected I2Cx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the I2C according to the specified parameters
+ * in the I2C_InitTypeDef and initialize the associated handle.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the I2C handle allocation */
+ if (hi2c == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1));
+ assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode));
+ assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode));
+ assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2));
+ assert_param(IS_I2C_OWN_ADDRESS2_MASK(hi2c->Init.OwnAddress2Masks));
+ assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode));
+ assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode));
+
+ if (hi2c->State == HAL_I2C_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hi2c->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ /* Init the I2C Callback settings */
+ hi2c->MasterTxCpltCallback = HAL_I2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
+ hi2c->MasterRxCpltCallback = HAL_I2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
+ hi2c->SlaveTxCpltCallback = HAL_I2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */
+ hi2c->SlaveRxCpltCallback = HAL_I2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */
+ hi2c->ListenCpltCallback = HAL_I2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */
+ hi2c->MemTxCpltCallback = HAL_I2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */
+ hi2c->MemRxCpltCallback = HAL_I2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */
+ hi2c->ErrorCallback = HAL_I2C_ErrorCallback; /* Legacy weak ErrorCallback */
+ hi2c->AbortCpltCallback = HAL_I2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ hi2c->AddrCallback = HAL_I2C_AddrCallback; /* Legacy weak AddrCallback */
+
+ if (hi2c->MspInitCallback == NULL)
+ {
+ hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ hi2c->MspInitCallback(hi2c);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_I2C_MspInit(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /*---------------------------- I2Cx TIMINGR Configuration ------------------*/
+ /* Configure I2Cx: Frequency range */
+ hi2c->Instance->TIMINGR = hi2c->Init.Timing & TIMING_CLEAR_MASK;
+
+ /*---------------------------- I2Cx OAR1 Configuration ---------------------*/
+ /* Disable Own Address1 before set the Own Address1 configuration */
+ hi2c->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
+
+ /* Configure I2Cx: Own Address1 and ack own address1 mode */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT)
+ {
+ hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | hi2c->Init.OwnAddress1);
+ }
+ else /* I2C_ADDRESSINGMODE_10BIT */
+ {
+ hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hi2c->Init.OwnAddress1);
+ }
+
+ /*---------------------------- I2Cx CR2 Configuration ----------------------*/
+ /* Configure I2Cx: Addressing Master mode */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ SET_BIT(hi2c->Instance->CR2, I2C_CR2_ADD10);
+ }
+ else
+ {
+ /* Clear the I2C ADD10 bit */
+ CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_ADD10);
+ }
+ /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
+ hi2c->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
+
+ /*---------------------------- I2Cx OAR2 Configuration ---------------------*/
+ /* Disable Own Address2 before set the Own Address2 configuration */
+ hi2c->Instance->OAR2 &= ~I2C_DUALADDRESS_ENABLE;
+
+ /* Configure I2Cx: Dual mode and Own Address2 */
+ hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2 | \
+ (hi2c->Init.OwnAddress2Masks << 8));
+
+ /*---------------------------- I2Cx CR1 Configuration ----------------------*/
+ /* Configure I2Cx: Generalcall and NoStretch mode */
+ hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode);
+
+ /* Enable the selected I2C peripheral */
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the I2C peripheral.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the I2C handle allocation */
+ if (hi2c == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the I2C Peripheral Clock */
+ __HAL_I2C_DISABLE(hi2c);
+
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ if (hi2c->MspDeInitCallback == NULL)
+ {
+ hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ hi2c->MspDeInitCallback(hi2c);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_I2C_MspDeInit(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_RESET;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the I2C MSP.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the I2C MSP.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User I2C Callback
+ * To be used instead of the weak predefined callback
+ * @note The HAL_I2C_RegisterCallback() may be called before HAL_I2C_Init() in HAL_I2C_STATE_RESET
+ * to register callbacks for HAL_I2C_MSPINIT_CB_ID and HAL_I2C_MSPDEINIT_CB_ID.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_I2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
+ * @arg @ref HAL_I2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID
+ * @arg @ref HAL_I2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_I2C_ABORT_CB_ID Abort callback ID
+ * @arg @ref HAL_I2C_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_I2C_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_RegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID,
+ pI2C_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MASTER_TX_COMPLETE_CB_ID :
+ hi2c->MasterTxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MASTER_RX_COMPLETE_CB_ID :
+ hi2c->MasterRxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_SLAVE_TX_COMPLETE_CB_ID :
+ hi2c->SlaveTxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_SLAVE_RX_COMPLETE_CB_ID :
+ hi2c->SlaveRxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_LISTEN_COMPLETE_CB_ID :
+ hi2c->ListenCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MEM_TX_COMPLETE_CB_ID :
+ hi2c->MemTxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MEM_RX_COMPLETE_CB_ID :
+ hi2c->MemRxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_ERROR_CB_ID :
+ hi2c->ErrorCallback = pCallback;
+ break;
+
+ case HAL_I2C_ABORT_CB_ID :
+ hi2c->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = pCallback;
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_I2C_STATE_RESET == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = pCallback;
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister an I2C Callback
+ * I2C callback is redirected to the weak predefined callback
+ * @note The HAL_I2C_UnRegisterCallback() may be called before HAL_I2C_Init() in HAL_I2C_STATE_RESET
+ * to un-register callbacks for HAL_I2C_MSPINIT_CB_ID and HAL_I2C_MSPDEINIT_CB_ID.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_I2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
+ * @arg @ref HAL_I2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID
+ * @arg @ref HAL_I2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_I2C_ABORT_CB_ID Abort callback ID
+ * @arg @ref HAL_I2C_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_I2C_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_UnRegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MASTER_TX_COMPLETE_CB_ID :
+ hi2c->MasterTxCpltCallback = HAL_I2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
+ break;
+
+ case HAL_I2C_MASTER_RX_COMPLETE_CB_ID :
+ hi2c->MasterRxCpltCallback = HAL_I2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
+ break;
+
+ case HAL_I2C_SLAVE_TX_COMPLETE_CB_ID :
+ hi2c->SlaveTxCpltCallback = HAL_I2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */
+ break;
+
+ case HAL_I2C_SLAVE_RX_COMPLETE_CB_ID :
+ hi2c->SlaveRxCpltCallback = HAL_I2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */
+ break;
+
+ case HAL_I2C_LISTEN_COMPLETE_CB_ID :
+ hi2c->ListenCpltCallback = HAL_I2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */
+ break;
+
+ case HAL_I2C_MEM_TX_COMPLETE_CB_ID :
+ hi2c->MemTxCpltCallback = HAL_I2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */
+ break;
+
+ case HAL_I2C_MEM_RX_COMPLETE_CB_ID :
+ hi2c->MemRxCpltCallback = HAL_I2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */
+ break;
+
+ case HAL_I2C_ERROR_CB_ID :
+ hi2c->ErrorCallback = HAL_I2C_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_I2C_ABORT_CB_ID :
+ hi2c->AbortCpltCallback = HAL_I2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_I2C_STATE_RESET == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register the Slave Address Match I2C Callback
+ * To be used instead of the weak HAL_I2C_AddrCallback() predefined callback
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pCallback pointer to the Address Match Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_RegisterAddrCallback(I2C_HandleTypeDef *hi2c, pI2C_AddrCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ hi2c->AddrCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Slave Address Match I2C Callback
+ * Info Ready I2C Callback is redirected to the weak HAL_I2C_AddrCallback() predefined callback
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_UnRegisterAddrCallback(I2C_HandleTypeDef *hi2c)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ hi2c->AddrCallback = HAL_I2C_AddrCallback; /* Legacy weak AddrCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Exported_Functions_Group2 Input and Output operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the I2C data
+ transfers.
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode : The communication is performed in the polling mode.
+ The status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode : The communication is performed using Interrupts
+ or DMA. These functions return the status of the transfer startup.
+ The end of the data processing will be indicated through the
+ dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (#) Blocking mode functions are :
+ (++) HAL_I2C_Master_Transmit()
+ (++) HAL_I2C_Master_Receive()
+ (++) HAL_I2C_Slave_Transmit()
+ (++) HAL_I2C_Slave_Receive()
+ (++) HAL_I2C_Mem_Write()
+ (++) HAL_I2C_Mem_Read()
+ (++) HAL_I2C_IsDeviceReady()
+
+ (#) No-Blocking mode functions with Interrupt are :
+ (++) HAL_I2C_Master_Transmit_IT()
+ (++) HAL_I2C_Master_Receive_IT()
+ (++) HAL_I2C_Slave_Transmit_IT()
+ (++) HAL_I2C_Slave_Receive_IT()
+ (++) HAL_I2C_Mem_Write_IT()
+ (++) HAL_I2C_Mem_Read_IT()
+ (++) HAL_I2C_Master_Seq_Transmit_IT()
+ (++) HAL_I2C_Master_Seq_Receive_IT()
+ (++) HAL_I2C_Slave_Seq_Transmit_IT()
+ (++) HAL_I2C_Slave_Seq_Receive_IT()
+ (++) HAL_I2C_EnableListen_IT()
+ (++) HAL_I2C_DisableListen_IT()
+ (++) HAL_I2C_Master_Abort_IT()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_I2C_Master_Transmit_DMA()
+ (++) HAL_I2C_Master_Receive_DMA()
+ (++) HAL_I2C_Slave_Transmit_DMA()
+ (++) HAL_I2C_Slave_Receive_DMA()
+ (++) HAL_I2C_Mem_Write_DMA()
+ (++) HAL_I2C_Mem_Read_DMA()
+ (++) HAL_I2C_Master_Seq_Transmit_DMA()
+ (++) HAL_I2C_Master_Seq_Receive_DMA()
+ (++) HAL_I2C_Slave_Seq_Transmit_DMA()
+ (++) HAL_I2C_Slave_Seq_Receive_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_I2C_MasterTxCpltCallback()
+ (++) HAL_I2C_MasterRxCpltCallback()
+ (++) HAL_I2C_SlaveTxCpltCallback()
+ (++) HAL_I2C_SlaveRxCpltCallback()
+ (++) HAL_I2C_MemTxCpltCallback()
+ (++) HAL_I2C_MemRxCpltCallback()
+ (++) HAL_I2C_AddrCallback()
+ (++) HAL_I2C_ListenCpltCallback()
+ (++) HAL_I2C_ErrorCallback()
+ (++) HAL_I2C_AbortCpltCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmits in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t xfermode;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)(hi2c->XferSize + 1U), xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ }
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receives in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ }
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmits in slave mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint16_t tmpXferCount;
+ HAL_StatusTypeDef error;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Preload TX data if no stretch enable */
+ if (hi2c->Init.NoStretchMode == I2C_NOSTRETCH_ENABLE)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ }
+
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* If 10bit addressing mode is selected */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Wait until DIR flag is set Transmitter mode */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ }
+
+ /* Wait until AF flag is set */
+ error = I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_AF, RESET, Timeout, tickstart);
+
+ if (error != HAL_OK)
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0 */
+
+ tmpXferCount = hi2c->XferCount;
+ if ((hi2c->ErrorCode == HAL_I2C_ERROR_AF) && (tmpXferCount == 0U))
+ {
+ /* Reset ErrorCode to NONE */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ else
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Clear AF flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Wait until STOP flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ /* Wait until BUSY flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in blocking mode
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferISR = NULL;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Wait until DIR flag is reset Receiver mode */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Store Last receive data if any */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* Wait until STOP flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Wait until BUSY flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
+ if (hi2c->XferSize > 0U)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)(hi2c->XferSize + 1U), xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, I2C_GENERATE_START_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ /* Preload TX data if no stretch enable */
+ if (hi2c->Init.NoStretchMode == I2C_NOSTRETCH_ENABLE)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Transmit in master mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+ HAL_StatusTypeDef dmaxferstatus;
+ uint32_t sizetoxfer = 0U;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ sizetoxfer = hi2c->XferSize;
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr,
+ (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)(hi2c->XferSize + 1U),
+ xfermode, I2C_GENERATE_START_WRITE);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and generate START condition */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address */
+ /* Set NBYTES to read and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, I2C_GENERATE_START_READ);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to read and generate START condition */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ /* Preload TX data if no stretch enable */
+ if (hi2c->Init.NoStretchMode == I2C_NOSTRETCH_ENABLE)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ if (hi2c->XferCount != 0U)
+ {
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx,
+ (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Write an amount of data in blocking mode to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address and Memory Address */
+ if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ do
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+
+ } while (hi2c->XferCount > 0U);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in blocking mode from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address and Memory Address */
+ if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+ }
+
+ do
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t) hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ } while (hi2c->XferCount > 0U);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->XferSize = 0U;
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_IT;
+ hi2c->Devaddress = DevAddress;
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_IT;
+ hi2c->Devaddress = DevAddress;
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_DMA;
+ hi2c->Devaddress = DevAddress;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_DMA;
+ hi2c->Devaddress = DevAddress;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Checks if target device is ready for communication.
+ * @note This function is used with Memory devices
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param Trials Number of trials
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ __IO uint32_t I2C_Trials = 0UL;
+
+ HAL_StatusTypeDef status = HAL_OK;
+
+ FlagStatus tmp1;
+ FlagStatus tmp2;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ do
+ {
+ /* Generate Start */
+ hi2c->Instance->CR2 = I2C_GENERATE_START(hi2c->Init.AddressingMode, DevAddress);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set or a NACK flag is set*/
+ tickstart = HAL_GetTick();
+
+ tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
+ tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
+
+ while ((tmp1 == RESET) && (tmp2 == RESET))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+
+ tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
+ tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
+ }
+
+ /* Check if the NACKF flag has not been set */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET)
+ {
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* A non acknowledge appear during STOP Flag waiting process, a new trial must be performed */
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Reset the error code for next trial */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* A acknowledge appear during STOP Flag waiting process, this mean that device respond to its address */
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Device is ready */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ }
+ else
+ {
+ /* A non acknowledge is detected, this mean that device not respond to its address,
+ a new trial must be performed */
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Clear STOP Flag, auto generated with autoend*/
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+ }
+
+ /* Increment Trials */
+ I2C_Trials++;
+
+ if ((I2C_Trials < Trials) && (status == HAL_ERROR))
+ {
+ status = HAL_OK;
+ }
+
+ } while (I2C_Trials < Trials);
+
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with Interrupt.
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_WRITE;
+ uint32_t sizetoxfer = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ if ((hi2c->XferSize > 0U) && ((XferOptions == I2C_FIRST_FRAME) || \
+ (XferOptions == I2C_FIRST_AND_LAST_FRAME)))
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ sizetoxfer = hi2c->XferSize;
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ /* Send Slave Address and set NBYTES to write */
+ if ((XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_FIRST_AND_LAST_FRAME))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with DMA.
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_WRITE;
+ HAL_StatusTypeDef dmaxferstatus;
+ uint32_t sizetoxfer = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ if ((hi2c->XferSize > 0U) && ((XferOptions == I2C_FIRST_FRAME) || \
+ (XferOptions == I2C_FIRST_AND_LAST_FRAME)))
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ sizetoxfer = hi2c->XferSize;
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr,
+ (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and set NBYTES to write */
+ if ((XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_FIRST_AND_LAST_FRAME))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+ }
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and generate START condition */
+ if ((XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_FIRST_AND_LAST_FRAME))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_READ;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ /* Send Slave Address and set NBYTES to read */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with DMA
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_READ;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and set NBYTES to read */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to read and generate START condition */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave RX state to TX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ /* Abort DMA Xfer if any */
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ }
+#endif /* HAL_DMA_MODULE_ENABLED */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with DMA
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave RX state to TX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmarx != NULL)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ }
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Reset XferSize */
+ hi2c->XferSize = 0;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave TX state to RX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ }
+#endif /* HAL_DMA_MODULE_ENABLED */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with DMA
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave TX state to RX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmatx != NULL)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ }
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA channel */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR,
+ (uint32_t)pData, hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Reset XferSize */
+ hi2c->XferSize = 0;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Enable the Address listen mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c)
+{
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ /* Enable the Address Match interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disable the Address listen mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ uint32_t tmp;
+
+ /* Disable Address listen mode only if a transfer is not ongoing */
+ if (hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK;
+ hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode);
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferISR = NULL;
+
+ /* Disable the Address Match interrupt */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Abort a master or memory I2C IT or DMA process communication with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress)
+{
+ HAL_I2C_ModeTypeDef tmp_mode = hi2c->Mode;
+
+ if ((tmp_mode == HAL_I2C_MODE_MASTER) || (tmp_mode == HAL_I2C_MODE_MEM))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Disable Interrupts and Store Previous state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Set State at HAL_I2C_STATE_ABORT */
+ hi2c->State = HAL_I2C_STATE_ABORT;
+
+ /* Set NBYTES to 1 to generate a dummy read on I2C peripheral */
+ /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
+ I2C_TransferConfig(hi2c, DevAddress, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Wrong usage of abort function */
+ /* This function should be used only in case of abort monitored by master device */
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
+ * @{
+ */
+
+/**
+ * @brief This function handles I2C event interrupt request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) /* Derogation MISRAC2012-Rule-8.13 */
+{
+ /* Get current IT Flags and IT sources value */
+ uint32_t itflags = READ_REG(hi2c->Instance->ISR);
+ uint32_t itsources = READ_REG(hi2c->Instance->CR1);
+
+ /* I2C events treatment -------------------------------------*/
+ if (hi2c->XferISR != NULL)
+ {
+ hi2c->XferISR(hi2c, itflags, itsources);
+ }
+}
+
+/**
+ * @brief This function handles I2C error interrupt request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c)
+{
+ uint32_t itflags = READ_REG(hi2c->Instance->ISR);
+ uint32_t itsources = READ_REG(hi2c->Instance->CR1);
+ uint32_t tmperror;
+
+ /* I2C Bus error interrupt occurred ------------------------------------*/
+ if ((I2C_CHECK_FLAG(itflags, I2C_FLAG_BERR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERRI) != RESET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_BERR;
+
+ /* Clear BERR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
+ }
+
+ /* I2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/
+ if ((I2C_CHECK_FLAG(itflags, I2C_FLAG_OVR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERRI) != RESET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_OVR;
+
+ /* Clear OVR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
+ }
+
+ /* I2C Arbitration Loss error interrupt occurred -------------------------------------*/
+ if ((I2C_CHECK_FLAG(itflags, I2C_FLAG_ARLO) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERRI) != RESET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO;
+
+ /* Clear ARLO flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
+ }
+
+ /* Store current volatile hi2c->ErrorCode, misra rule */
+ tmperror = hi2c->ErrorCode;
+
+ /* Call the Error Callback in case of Error detected */
+ if ((tmperror & (HAL_I2C_ERROR_BERR | HAL_I2C_ERROR_OVR | HAL_I2C_ERROR_ARLO)) != HAL_I2C_ERROR_NONE)
+ {
+ I2C_ITError(hi2c, tmperror);
+ }
+}
+
+/**
+ * @brief Master Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MasterTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Master Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MasterRxCpltCallback could be implemented in the user file
+ */
+}
+
+/** @brief Slave Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Address Match callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XFERDIRECTION
+ * @param AddrMatchCode Address Match Code
+ * @retval None
+ */
+__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+ UNUSED(TransferDirection);
+ UNUSED(AddrMatchCode);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_AddrCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Listen Complete callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_ListenCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MemTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MemRxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C error callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C abort callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_AbortCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions
+ * @brief Peripheral State, Mode and Error functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State, Mode and Error functions #####
+ ===============================================================================
+ [..]
+ This subsection permit to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the I2C handle state.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL state
+ */
+HAL_I2C_StateTypeDef HAL_I2C_GetState(const I2C_HandleTypeDef *hi2c)
+{
+ /* Return I2C handle state */
+ return hi2c->State;
+}
+
+/**
+ * @brief Returns the I2C Master, Slave, Memory or no mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for I2C module
+ * @retval HAL mode
+ */
+HAL_I2C_ModeTypeDef HAL_I2C_GetMode(const I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->Mode;
+}
+
+/**
+ * @brief Return the I2C error code.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval I2C Error Code
+ */
+uint32_t HAL_I2C_GetError(const I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2C_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint16_t devaddress;
+ uint32_t tmpITFlags = ITFlags;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ /* No need to generate STOP, it is automatically done */
+ /* Error callback will be send during stop flag treatment */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_RXI) != RESET))
+ {
+ /* Remove RXNE flag on temporary variable as read done */
+ tmpITFlags &= ~I2C_FLAG_RXNE;
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TC) == RESET) && \
+ ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET)))
+ {
+ /* Write data to TXDR */
+ if (hi2c->XferCount != 0U)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ devaddress = (uint16_t)(hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ if (hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize,
+ hi2c->XferOptions, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ }
+ else
+ {
+ /* Call TxCpltCallback() if no stop mode is set */
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if (hi2c->XferCount == 0U)
+ {
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Generate a stop condition in case of no transfer option */
+ if (hi2c->XferOptions == I2C_NO_OPTION_FRAME)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ else
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TC flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, tmpITFlags);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Mem_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t direction = I2C_GENERATE_START_WRITE;
+ uint32_t tmpITFlags = ITFlags;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ /* No need to generate STOP, it is automatically done */
+ /* Error callback will be send during stop flag treatment */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_RXI) != RESET))
+ {
+ /* Remove RXNE flag on temporary variable as read done */
+ tmpITFlags &= ~I2C_FLAG_RXNE;
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ if (hi2c->Memaddress == 0xFFFFFFFFU)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else
+ {
+ /* Write LSB part of Memory Address */
+ hi2c->Instance->TXDR = hi2c->Memaddress;
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable Interrupt related to address step */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Enable ERR, TC, STOP, NACK and RXI interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ direction = I2C_GENERATE_START_READ;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, direction);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+
+ /* Set NBYTES to write and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, direction);
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, tmpITFlags);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t tmpoptions = hi2c->XferOptions;
+ uint32_t tmpITFlags = ITFlags;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ /* Check if STOPF is set */
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Slave complete process */
+ I2C_ITSlaveCplt(hi2c, tmpITFlags);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if (hi2c->XferCount == 0U)
+ {
+ if ((hi2c->State == HAL_I2C_STATE_LISTEN) && (tmpoptions == I2C_FIRST_AND_LAST_FRAME))
+ /* Same action must be done for (tmpoptions == I2C_LAST_FRAME) which removed for
+ Warning[Pa134]: left and right operands are identical */
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, tmpITFlags);
+ }
+ else if ((hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ if ((tmpoptions == I2C_FIRST_FRAME) || (tmpoptions == I2C_NEXT_FRAME))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_RXI) != RESET))
+ {
+ if (hi2c->XferCount > 0U)
+ {
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+
+ if ((hi2c->XferCount == 0U) && \
+ (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_ADDR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_ADDRI) != RESET))
+ {
+ I2C_ITAddrCplt(hi2c, tmpITFlags);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ /* Write data to TXDR only if XferCount not reach "0" */
+ /* A TXIS flag can be set, during STOP treatment */
+ /* Check if all Data have already been sent */
+ /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
+ if (hi2c->XferCount > 0U)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+ else
+ {
+ if ((tmpoptions == I2C_NEXT_FRAME) || (tmpoptions == I2C_FIRST_FRAME))
+ {
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with DMA.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint16_t devaddress;
+ uint32_t xfermode;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* No need to generate STOP, it is automatically done */
+ /* But enable STOP interrupt, to treat it */
+ /* Error callback will be send during stop flag treatment */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable TC interrupt */
+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_TCI);
+
+ if (hi2c->XferCount != 0U)
+ {
+ /* Recover Slave address */
+ devaddress = (uint16_t)(hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ /* Prepare the new XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ if (hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ else
+ {
+ xfermode = I2C_AUTOEND_MODE;
+ }
+ }
+
+ /* Set the new XferSize in Nbytes register */
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize, xfermode, I2C_NO_STARTSTOP);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Enable DMA Request */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ else
+ {
+ /* Call TxCpltCallback() if no stop mode is set */
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if (hi2c->XferCount == 0U)
+ {
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Generate a stop condition in case of no transfer option */
+ if (hi2c->XferOptions == I2C_NO_OPTION_FRAME)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ else
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TC flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, ITFlags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with DMA.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Mem_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t direction = I2C_GENERATE_START_WRITE;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* No need to generate STOP, it is automatically done */
+ /* But enable STOP interrupt, to treat it */
+ /* Error callback will be send during stop flag treatment */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ /* Write LSB part of Memory Address */
+ hi2c->Instance->TXDR = hi2c->Memaddress;
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable Interrupt related to address step */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Enable only Error interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ if (hi2c->XferCount != 0U)
+ {
+ /* Prepare the new XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Enable DMA Request */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable Interrupt related to address step */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Enable only Error and NACK interrupt for data transfer */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ direction = I2C_GENERATE_START_READ;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, direction);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+
+ /* Set NBYTES to write and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, direction);
+ }
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Enable DMA Request */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, ITFlags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t tmpoptions = hi2c->XferOptions;
+ uint32_t treatdmanack = 0U;
+ HAL_I2C_StateTypeDef tmpstate;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ /* Check if STOPF is set */
+ if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Slave complete process */
+ I2C_ITSlaveCplt(hi2c, ITFlags);
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0 */
+ /* So clear Flag NACKF only */
+ if ((I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_TXDMAEN) != RESET) ||
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_RXDMAEN) != RESET))
+ {
+ /* Split check of hdmarx, for MISRA compliance */
+ if (hi2c->hdmarx != NULL)
+ {
+ if (I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_RXDMAEN) != RESET)
+ {
+ if (I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx) == 0U)
+ {
+ treatdmanack = 1U;
+ }
+ }
+ }
+
+ /* Split check of hdmatx, for MISRA compliance */
+ if (hi2c->hdmatx != NULL)
+ {
+ if (I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_TXDMAEN) != RESET)
+ {
+ if (I2C_GET_DMA_REMAIN_DATA(hi2c->hdmatx) == 0U)
+ {
+ treatdmanack = 1U;
+ }
+ }
+ }
+
+ if (treatdmanack == 1U)
+ {
+ if ((hi2c->State == HAL_I2C_STATE_LISTEN) && (tmpoptions == I2C_FIRST_AND_LAST_FRAME))
+ /* Same action must be done for (tmpoptions == I2C_LAST_FRAME) which removed for
+ Warning[Pa134]: left and right operands are identical */
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, ITFlags);
+ }
+ else if ((hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Store current hi2c->State, solve MISRA2012-Rule-13.5 */
+ tmpstate = hi2c->State;
+
+ if ((tmpoptions == I2C_FIRST_FRAME) || (tmpoptions == I2C_NEXT_FRAME))
+ {
+ if ((tmpstate == HAL_I2C_STATE_BUSY_TX) || (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN))
+ {
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+ }
+ else if ((tmpstate == HAL_I2C_STATE_BUSY_RX) || (tmpstate == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ }
+ }
+ else
+ {
+ /* Only Clear NACK Flag, no DMA treatment is pending */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_ADDR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_ADDRI) != RESET))
+ {
+ I2C_ITAddrCplt(hi2c, ITFlags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief Master sends target device address followed by internal memory address for write request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Send Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Send MSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Send LSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Master sends target device address followed by internal memory address for read request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Send Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Send MSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Send LSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ /* Wait until TC flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief I2C Address complete process callback.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ uint8_t transferdirection;
+ uint16_t slaveaddrcode;
+ uint16_t ownadd1code;
+ uint16_t ownadd2code;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ITFlags);
+
+ /* In case of Listen state, need to inform upper layer of address match code event */
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ transferdirection = I2C_GET_DIR(hi2c);
+ slaveaddrcode = I2C_GET_ADDR_MATCH(hi2c);
+ ownadd1code = I2C_GET_OWN_ADDRESS1(hi2c);
+ ownadd2code = I2C_GET_OWN_ADDRESS2(hi2c);
+
+ /* If 10bits addressing mode is selected */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ if ((slaveaddrcode & SLAVE_ADDR_MSK) == ((ownadd1code >> SLAVE_ADDR_SHIFT) & SLAVE_ADDR_MSK))
+ {
+ slaveaddrcode = ownadd1code;
+ hi2c->AddrEventCount++;
+ if (hi2c->AddrEventCount == 2U)
+ {
+ /* Reset Address Event counter */
+ hi2c->AddrEventCount = 0U;
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#else
+ HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ slaveaddrcode = ownadd2code;
+
+ /* Disable ADDR Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#else
+ HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ /* else 7 bits addressing mode is selected */
+ else
+ {
+ /* Disable ADDR Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#else
+ HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ /* Else clear address flag only */
+ else
+ {
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+}
+
+/**
+ * @brief I2C Master sequential complete process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_ITMasterSeqCplt(I2C_HandleTypeDef *hi2c)
+{
+ /* Reset I2C handle mode */
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* No Generate Stop, to permit restart mode */
+ /* The stop will be done at the end of transfer, when I2C_AUTOEND_MODE enable */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ hi2c->XferISR = NULL;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterTxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_RX */
+ else
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ hi2c->XferISR = NULL;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterRxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief I2C Slave sequential complete process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_ITSlaveSeqCplt(I2C_HandleTypeDef *hi2c)
+{
+ uint32_t tmpcr1value = READ_REG(hi2c->Instance->CR1);
+
+ /* Reset I2C handle mode */
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ /* If a DMA is ongoing, Update handle size context */
+ if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_TXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+ }
+ else if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_RXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_TX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveTxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_RX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveRxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief I2C Master complete process.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ uint32_t tmperror;
+ uint32_t tmpITFlags = ITFlags;
+ __IO uint32_t tmpreg;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Disable Interrupts and Store Previous state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Reset handle parameters */
+ hi2c->XferISR = NULL;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ if (I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set acknowledge error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ /* Fetch Last receive data if any */
+ if ((hi2c->State == HAL_I2C_STATE_ABORT) && (I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET))
+ {
+ /* Read data from RXDR */
+ tmpreg = (uint8_t)hi2c->Instance->RXDR;
+ UNUSED(tmpreg);
+ }
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Store current volatile hi2c->ErrorCode, misra rule */
+ tmperror = hi2c->ErrorCode;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if ((hi2c->State == HAL_I2C_STATE_ABORT) || (tmperror != HAL_I2C_ERROR_NONE))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_TX */
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ if (hi2c->Mode == HAL_I2C_MODE_MEM)
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MemTxCpltCallback(hi2c);
+#else
+ HAL_I2C_MemTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterTxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_RX */
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ if (hi2c->Mode == HAL_I2C_MODE_MEM)
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MemRxCpltCallback(hi2c);
+#else
+ HAL_I2C_MemRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterRxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief I2C Slave complete process.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ uint32_t tmpcr1value = READ_REG(hi2c->Instance->CR1);
+ uint32_t tmpITFlags = ITFlags;
+ uint32_t tmpoptions = hi2c->XferOptions;
+ HAL_I2C_StateTypeDef tmpstate = hi2c->State;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Disable Interrupts and Store Previous state */
+ if ((tmpstate == HAL_I2C_STATE_BUSY_TX) || (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN))
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+ }
+ else if ((tmpstate == HAL_I2C_STATE_BUSY_RX) || (tmpstate == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+ }
+ else if (tmpstate == HAL_I2C_STATE_LISTEN)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT | I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_NONE;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ /* If a DMA is ongoing, Update handle size context */
+ if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_TXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ if (hi2c->hdmatx != NULL)
+ {
+ hi2c->XferCount = (uint16_t)I2C_GET_DMA_REMAIN_DATA(hi2c->hdmatx);
+ }
+ }
+ else if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_RXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ hi2c->XferCount = (uint16_t)I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx);
+ }
+ }
+ else
+ {
+ /* Do nothing */
+ }
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+ /* Store Last receive data if any */
+ if (I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET)
+ {
+ /* Remove RXNE flag on temporary variable as read done */
+ tmpITFlags &= ~I2C_FLAG_RXNE;
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ if (hi2c->XferSize > 0U)
+ {
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ }
+
+ /* All data are not transferred, so set error code accordingly */
+ if (hi2c->XferCount != 0U)
+ {
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_IT_NACKI) != RESET))
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if (hi2c->XferCount == 0U)
+ {
+ if ((hi2c->State == HAL_I2C_STATE_LISTEN) && (tmpoptions == I2C_FIRST_AND_LAST_FRAME))
+ /* Same action must be done for (tmpoptions == I2C_LAST_FRAME) which removed for
+ Warning[Pa134]: left and right operands are identical */
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, tmpITFlags);
+ }
+ else if ((hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ if ((tmpoptions == I2C_FIRST_FRAME) || (tmpoptions == I2C_NEXT_FRAME))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ }
+ }
+
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferISR = NULL;
+
+ if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+ if (hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, tmpITFlags);
+ }
+ }
+ else if (hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ /* Call the Sequential Complete callback, to inform upper layer of the end of Transfer */
+ I2C_ITSlaveSeqCplt(hi2c);
+
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->ListenCpltCallback(hi2c);
+#else
+ HAL_I2C_ListenCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveRxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveTxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief I2C Listen complete process.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ /* Reset handle parameters */
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferISR = NULL;
+
+ /* Store Last receive data if any */
+ if (I2C_CHECK_FLAG(ITFlags, I2C_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ if (hi2c->XferSize > 0U)
+ {
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ }
+
+ /* Disable all Interrupts*/
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->ListenCpltCallback(hi2c);
+#else
+ HAL_I2C_ListenCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief I2C interrupts error process.
+ * @param hi2c I2C handle.
+ * @param ErrorCode Error code to handle.
+ * @retval None
+ */
+static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode)
+{
+ HAL_I2C_StateTypeDef tmpstate = hi2c->State;
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ uint32_t tmppreviousstate;
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+ /* Reset handle parameters */
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferCount = 0U;
+
+ /* Set new error code */
+ hi2c->ErrorCode |= ErrorCode;
+
+ /* Disable Interrupts */
+ if ((tmpstate == HAL_I2C_STATE_LISTEN) ||
+ (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN) ||
+ (tmpstate == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ /* Disable all interrupts, except interrupts related to LISTEN state */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* keep HAL_I2C_STATE_LISTEN if set */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+ }
+ else
+ {
+ /* Disable all interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* If state is an abort treatment on going, don't change state */
+ /* This change will be do later */
+ if (hi2c->State != HAL_I2C_STATE_ABORT)
+ {
+ /* Set HAL_I2C_STATE_READY */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Check if a STOPF is detected */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ }
+ hi2c->XferISR = NULL;
+ }
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ /* Abort DMA TX transfer if any */
+ tmppreviousstate = hi2c->PreviousState;
+
+ if ((hi2c->hdmatx != NULL) && ((tmppreviousstate == I2C_STATE_MASTER_BUSY_TX) || \
+ (tmppreviousstate == I2C_STATE_SLAVE_BUSY_TX)))
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+ }
+
+ if (HAL_DMA_GetState(hi2c->hdmatx) != HAL_DMA_STATE_READY)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ else
+ {
+ I2C_TreatErrorCallback(hi2c);
+ }
+ }
+ /* Abort DMA RX transfer if any */
+ else if ((hi2c->hdmarx != NULL) && ((tmppreviousstate == I2C_STATE_MASTER_BUSY_RX) || \
+ (tmppreviousstate == I2C_STATE_SLAVE_BUSY_RX)))
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+ }
+
+ if (HAL_DMA_GetState(hi2c->hdmarx) != HAL_DMA_STATE_READY)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ else
+ {
+ I2C_TreatErrorCallback(hi2c);
+ }
+ }
+ else
+#endif /* HAL_DMA_MODULE_ENABLED */
+ {
+ I2C_TreatErrorCallback(hi2c);
+ }
+}
+
+/**
+ * @brief I2C Error callback treatment.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_TreatErrorCallback(I2C_HandleTypeDef *hi2c)
+{
+ if (hi2c->State == HAL_I2C_STATE_ABORT)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AbortCpltCallback(hi2c);
+#else
+ HAL_I2C_AbortCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->ErrorCallback(hi2c);
+#else
+ HAL_I2C_ErrorCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief I2C Tx data register flush process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c)
+{
+ /* If a pending TXIS flag is set */
+ /* Write a dummy data in TXDR to clear it */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ hi2c->Instance->TXDR = 0x00U;
+ }
+
+ /* Flush TX register if not empty */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+}
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+/**
+ * @brief DMA I2C master transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* If last transfer, enable STOP interrupt */
+ if (hi2c->XferCount == 0U)
+ {
+ /* Enable STOP interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+ }
+ /* else prepare a new DMA transfer and enable TCReload interrupt */
+ else
+ {
+ /* Update Buffer pointer */
+ hi2c->pBuffPtr += hi2c->XferSize;
+
+ /* Set the XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize) != HAL_OK)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
+ }
+ else
+ {
+ /* Enable TC interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT);
+ }
+ }
+}
+
+
+/**
+ * @brief DMA I2C slave transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tmpoptions = hi2c->XferOptions;
+
+ if ((tmpoptions == I2C_NEXT_FRAME) || (tmpoptions == I2C_FIRST_FRAME))
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* No specific action, Master fully manage the generation of STOP condition */
+ /* Mean that this generation can arrive at any time, at the end or during DMA process */
+ /* So STOP condition should be manage through Interrupt treatment */
+ }
+}
+
+
+/**
+ * @brief DMA I2C master receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* If last transfer, enable STOP interrupt */
+ if (hi2c->XferCount == 0U)
+ {
+ /* Enable STOP interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+ }
+ /* else prepare a new DMA transfer and enable TCReload interrupt */
+ else
+ {
+ /* Update Buffer pointer */
+ hi2c->pBuffPtr += hi2c->XferSize;
+
+ /* Set the XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* Enable the DMA channel */
+ if (HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr,
+ hi2c->XferSize) != HAL_OK)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
+ }
+ else
+ {
+ /* Enable TC interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT);
+ }
+ }
+}
+
+
+/**
+ * @brief DMA I2C slave receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tmpoptions = hi2c->XferOptions;
+
+ if ((I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx) == 0U) && \
+ (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* No specific action, Master fully manage the generation of STOP condition */
+ /* Mean that this generation can arrive at any time, at the end or during DMA process */
+ /* So STOP condition should be manage through Interrupt treatment */
+ }
+}
+
+
+/**
+ * @brief DMA I2C communication error callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAError(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Disable Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
+}
+
+
+/**
+ * @brief DMA I2C communication abort callback
+ * (To be called at end of DMA Abort procedure).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void I2C_DMAAbort(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Reset AbortCpltCallback */
+ if (hi2c->hdmatx != NULL)
+ {
+ hi2c->hdmatx->XferAbortCallback = NULL;
+ }
+ if (hi2c->hdmarx != NULL)
+ {
+ hi2c->hdmarx->XferAbortCallback = NULL;
+ }
+
+ I2C_TreatErrorCallback(hi2c);
+}
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+/**
+ * @brief This function handles I2C Communication Timeout. It waits
+ * until a flag is no longer in the specified status.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Flag Specifies the I2C flag to check.
+ * @param Status The actual Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status,
+ uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of TXIS flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of STOP flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ while ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) && (status == HAL_OK))
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Check if a STOPF is detected */
+ if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) && (status == HAL_OK))
+ {
+ /* Check if an RXNE is pending */
+ /* Store Last receive data if any */
+ if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) && (hi2c->XferSize > 0U))
+ {
+ /* Return HAL_OK */
+ /* The Reading of data from RXDR will be done in caller function */
+ status = HAL_OK;
+ }
+
+ /* Check a no-acknowledge have been detected */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ hi2c->ErrorCode = HAL_I2C_ERROR_AF;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ status = HAL_ERROR;
+ }
+ else
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ }
+
+ /* Check for the Timeout */
+ if ((((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) && (status == HAL_OK))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ status = HAL_ERROR;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief This function handles errors detection during an I2C Communication.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_IsErrorOccurred(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t itflag = hi2c->Instance->ISR;
+ uint32_t error_code = 0;
+ uint32_t tickstart = Tickstart;
+ uint32_t tmp1;
+ HAL_I2C_ModeTypeDef tmp2;
+
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_AF))
+ {
+ /* Clear NACKF Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Wait until STOP Flag is set or timeout occurred */
+ /* AutoEnd should be initiate after AF */
+ while ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) && (status == HAL_OK))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ tmp1 = (uint32_t)(hi2c->Instance->CR2 & I2C_CR2_STOP);
+ tmp2 = hi2c->Mode;
+
+ /* In case of I2C still busy, try to regenerate a STOP manually */
+ if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET) && \
+ (tmp1 != I2C_CR2_STOP) && \
+ (tmp2 != HAL_I2C_MODE_SLAVE))
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+
+ /* Update Tick with new reference */
+ tickstart = HAL_GetTick();
+ }
+
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > I2C_TIMEOUT_STOPF)
+ {
+ error_code |= HAL_I2C_ERROR_TIMEOUT;
+
+ status = HAL_ERROR;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* In case STOP Flag is detected, clear it */
+ if (status == HAL_OK)
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ error_code |= HAL_I2C_ERROR_AF;
+
+ status = HAL_ERROR;
+ }
+
+ /* Refresh Content of Status register */
+ itflag = hi2c->Instance->ISR;
+
+ /* Then verify if an additional errors occurs */
+ /* Check if a Bus error occurred */
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_BERR))
+ {
+ error_code |= HAL_I2C_ERROR_BERR;
+
+ /* Clear BERR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
+
+ status = HAL_ERROR;
+ }
+
+ /* Check if an Over-Run/Under-Run error occurred */
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_OVR))
+ {
+ error_code |= HAL_I2C_ERROR_OVR;
+
+ /* Clear OVR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
+
+ status = HAL_ERROR;
+ }
+
+ /* Check if an Arbitration Loss error occurred */
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_ARLO))
+ {
+ error_code |= HAL_I2C_ERROR_ARLO;
+
+ /* Clear ARLO flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
+
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_OK)
+ {
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode |= error_code;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
+ * @param hi2c I2C handle.
+ * @param DevAddress Specifies the slave address to be programmed.
+ * @param Size Specifies the number of bytes to be programmed.
+ * This parameter must be a value between 0 and 255.
+ * @param Mode New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_RELOAD_MODE Enable Reload mode .
+ * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
+ * @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
+ * @param Request New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
+ * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
+ * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
+ * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
+ * @retval None
+ */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
+ uint32_t Request)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_TRANSFER_MODE(Mode));
+ assert_param(IS_TRANSFER_REQUEST(Request));
+
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ tmp = ((uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | \
+ (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | \
+ (uint32_t)Mode | (uint32_t)Request) & (~0x80000000U));
+
+ /* update CR2 register */
+ MODIFY_REG(hi2c->Instance->CR2, \
+ ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | \
+ (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | \
+ I2C_CR2_START | I2C_CR2_STOP)), tmp);
+}
+
+/**
+ * @brief Manage the enabling of Interrupts.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition.
+ * @retval None
+ */
+static void I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest)
+{
+ uint32_t tmpisr = 0U;
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ if ((hi2c->XferISR != I2C_Master_ISR_DMA) && \
+ (hi2c->XferISR != I2C_Slave_ISR_DMA) && \
+ (hi2c->XferISR != I2C_Mem_ISR_DMA))
+#endif /* HAL_DMA_MODULE_ENABLED */
+ {
+ if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Enable ERR, STOP, NACK and ADDR interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and TXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and RXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI;
+ }
+
+ if (InterruptRequest == I2C_XFER_ERROR_IT)
+ {
+ /* Enable ERR and NACK interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= I2C_IT_STOPI;
+ }
+ }
+
+#if defined(HAL_DMA_MODULE_ENABLED)
+ else
+ {
+ if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Enable ERR, STOP, NACK and ADDR interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and TXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and RXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI;
+ }
+
+ if (InterruptRequest == I2C_XFER_ERROR_IT)
+ {
+ /* Enable ERR and NACK interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= (I2C_IT_STOPI | I2C_IT_TCI);
+ }
+
+ if (InterruptRequest == I2C_XFER_RELOAD_IT)
+ {
+ /* Enable TC interrupts */
+ tmpisr |= I2C_IT_TCI;
+ }
+ }
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+ /* Enable interrupts only at the end */
+ /* to avoid the risk of I2C interrupt handle execution before */
+ /* all interrupts requested done */
+ __HAL_I2C_ENABLE_IT(hi2c, tmpisr);
+}
+
+/**
+ * @brief Manage the disabling of Interrupts.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition.
+ * @retval None
+ */
+static void I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest)
+{
+ uint32_t tmpisr = 0U;
+
+ if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Disable TC and TXI interrupts */
+ tmpisr |= I2C_IT_TCI | I2C_IT_TXI;
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) != (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ /* Disable NACK and STOP interrupts */
+ tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+ }
+
+ if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Disable TC and RXI interrupts */
+ tmpisr |= I2C_IT_TCI | I2C_IT_RXI;
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) != (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ /* Disable NACK and STOP interrupts */
+ tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+ }
+
+ if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Disable ADDR, NACK and STOP interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if (InterruptRequest == I2C_XFER_ERROR_IT)
+ {
+ /* Enable ERR and NACK interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= I2C_IT_STOPI;
+ }
+
+ if (InterruptRequest == I2C_XFER_RELOAD_IT)
+ {
+ /* Enable TC interrupts */
+ tmpisr |= I2C_IT_TCI;
+ }
+
+ /* Disable interrupts only at the end */
+ /* to avoid a breaking situation like at "t" time */
+ /* all disable interrupts request are not done */
+ __HAL_I2C_DISABLE_IT(hi2c, tmpisr);
+}
+
+/**
+ * @brief Convert I2Cx OTHER_xxx XferOptions to functional XferOptions.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_ConvertOtherXferOptions(I2C_HandleTypeDef *hi2c)
+{
+ /* if user set XferOptions to I2C_OTHER_FRAME */
+ /* it request implicitly to generate a restart condition */
+ /* set XferOptions to I2C_FIRST_FRAME */
+ if (hi2c->XferOptions == I2C_OTHER_FRAME)
+ {
+ hi2c->XferOptions = I2C_FIRST_FRAME;
+ }
+ /* else if user set XferOptions to I2C_OTHER_AND_LAST_FRAME */
+ /* it request implicitly to generate a restart condition */
+ /* then generate a stop condition at the end of transfer */
+ /* set XferOptions to I2C_FIRST_AND_LAST_FRAME */
+ else if (hi2c->XferOptions == I2C_OTHER_AND_LAST_FRAME)
+ {
+ hi2c->XferOptions = I2C_FIRST_AND_LAST_FRAME;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c_ex.c
new file mode 100644
index 0000000..eb31914
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_i2c_ex.c
@@ -0,0 +1,354 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_i2c_ex.c
+ * @author MCD Application Team
+ * @brief I2C Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of I2C Extended peripheral:
+ * + Filter Mode Functions
+ * + WakeUp Mode Functions
+ * + FastModePlus Functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### I2C peripheral Extended features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the I2C interface for STM32WBxx
+ devices contains the following additional features
+
+ (+) Possibility to disable or enable Analog Noise Filter
+ (+) Use of a configured Digital Noise Filter
+ (+) Disable or enable wakeup from Stop mode(s)
+ (+) Disable or enable Fast Mode Plus
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure Noise Filter and Wake Up Feature
+ (#) Configure I2C Analog noise filter using the function HAL_I2CEx_ConfigAnalogFilter()
+ (#) Configure I2C Digital noise filter using the function HAL_I2CEx_ConfigDigitalFilter()
+ (#) Configure the enable or disable of I2C Wake Up Mode using the functions :
+ (++) HAL_I2CEx_EnableWakeUp()
+ (++) HAL_I2CEx_DisableWakeUp()
+ (#) Configure the enable or disable of fast mode plus driving capability using the functions :
+ (++) HAL_I2CEx_EnableFastModePlus()
+ (++) HAL_I2CEx_DisableFastModePlus()
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2CEx I2CEx
+ * @brief I2C Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup I2CEx_Exported_Functions I2C Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group1 Filter Mode Functions
+ * @brief Filter Mode Functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Filter Mode Functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Noise Filters
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure I2C Analog noise filter.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @param AnalogFilter New state of the Analog filter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Reset I2Cx ANOFF bit */
+ hi2c->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
+
+ /* Set analog filter bit*/
+ hi2c->Instance->CR1 |= AnalogFilter;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Configure I2C Digital noise filter.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Get the old register value */
+ tmpreg = hi2c->Instance->CR1;
+
+ /* Reset I2Cx DNF bits [11:8] */
+ tmpreg &= ~(I2C_CR1_DNF);
+
+ /* Set I2Cx DNF coefficient */
+ tmpreg |= DigitalFilter << 8U;
+
+ /* Store the new register value */
+ hi2c->Instance->CR1 = tmpreg;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group2 WakeUp Mode Functions
+ * @brief WakeUp Mode Functions
+ *
+@verbatim
+ ===============================================================================
+ ##### WakeUp Mode Functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Wake Up Feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable I2C wakeup from Stop mode(s).
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Enable wakeup from stop mode */
+ hi2c->Instance->CR1 |= I2C_CR1_WUPEN;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disable I2C wakeup from Stop mode(s).
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Enable wakeup from stop mode */
+ hi2c->Instance->CR1 &= ~(I2C_CR1_WUPEN);
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group3 Fast Mode Plus Functions
+ * @brief Fast Mode Plus Functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Fast Mode Plus Functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Fast Mode Plus
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the I2C fast mode plus driving capability.
+ * @param ConfigFastModePlus Selects the pin.
+ * This parameter can be one of the @ref I2CEx_FastModePlus values
+ * @note For I2C1, fast mode plus driving capability can be enabled on all selected
+ * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
+ * on each one of the following pins PB6, PB7, PB8 and PB9.
+ * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
+ * can be enabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
+ * @note For all I2C3 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C3 parameter.
+ * @retval None
+ */
+void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus)
+{
+ /* Check the parameter */
+ assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
+
+ /* Enable fast mode plus driving capability for selected pin */
+ SET_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus);
+}
+
+/**
+ * @brief Disable the I2C fast mode plus driving capability.
+ * @param ConfigFastModePlus Selects the pin.
+ * This parameter can be one of the @ref I2CEx_FastModePlus values
+ * @note For I2C1, fast mode plus driving capability can be disabled on all selected
+ * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
+ * on each one of the following pins PB6, PB7, PB8 and PB9.
+ * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
+ * can be disabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
+ * @note For all I2C3 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C3 parameter.
+ * @retval None
+ */
+void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus)
+{
+ /* Check the parameter */
+ assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
+
+ /* Disable fast mode plus driving capability for selected pin */
+ CLEAR_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus);
+}
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_ipcc.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_ipcc.c
new file mode 100644
index 0000000..22d16f8
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_ipcc.c
@@ -0,0 +1,755 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_ipcc.c
+ * @author MCD Application Team
+ * @brief IPCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Inter-Processor communication controller
+ * peripherals (IPCC).
+ * + Initialization and de-initialization functions
+ * + Configuration, notification and interrupts handling
+ * + Peripheral State and Error functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The IPCC HAL driver can be used as follows:
+
+ (#) Declare a IPCC_HandleTypeDef handle structure, for example: IPCC_HandleTypeDef hipcc;
+ (#) Initialize the IPCC low level resources by implementing the HAL_IPCC_MspInit() API:
+ (##) Enable the IPCC interface clock
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the IPCC interrupt priority
+ (+++) Enable the NVIC IPCC IRQ
+
+ (#) Initialize the IPCC registers by calling the HAL_IPCC_Init() API which trig
+ HAL_IPCC_MspInit().
+
+ (#) Implement the interrupt callbacks for transmission and reception to use the driver in interrupt mode
+
+ (#) Associate those callback to the corresponding channel and direction using HAL_IPCC_ConfigChannel().
+ This is the interrupt mode.
+ If no callback are configured for a given channel and direction, it is up to the user to poll the
+ status of the communication (polling mode).
+
+ (#) Notify the other MCU when a message is available in a chosen channel
+ or when a message has been retrieved from a chosen channel by calling
+ the HAL_IPCC_NotifyCPU() API.
+
+@endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+#if defined(IPCC)
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup IPCC
+ * @{
+ */
+
+#ifdef HAL_IPCC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup IPCC_Private_Constants IPCC Private Constants
+ * @{
+ */
+#define IPCC_ALL_RX_BUF 0x0000003FU /*!< Mask for all RX buffers. */
+#define IPCC_ALL_TX_BUF 0x003F0000U /*!< Mask for all TX buffers. */
+#define CHANNEL_INDEX_MASK 0x0000000FU /*!< Mask the channel index to avoid overflow */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup IPCC_Private_Functions IPCC Private Functions
+ * @{
+ */
+void IPCC_MaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
+void IPCC_UnmaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
+void IPCC_SetDefaultCallbacks(IPCC_HandleTypeDef *hipcc);
+void IPCC_Reset_Register(IPCC_CommonTypeDef *Instance);
+/**
+ * @}
+ */
+
+/** @addtogroup IPCC_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup IPCC_Exported_Functions_Group1
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ deinitialize the IPCC peripheral:
+
+ (+) User must Implement HAL_IPCC_MspInit() function in which he configures
+ all related peripherals resources (CLOCK and NVIC ).
+
+ (+) Call the function HAL_IPCC_Init() to configure the IPCC register.
+
+ (+) Call the function HAL_PKA_DeInit() to restore the default configuration
+ of the selected IPCC peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the IPCC peripheral.
+ * @param hipcc IPCC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IPCC_Init(IPCC_HandleTypeDef *hipcc)
+{
+ HAL_StatusTypeDef err = HAL_OK;
+
+ /* Check the IPCC handle allocation */
+ if (hipcc != NULL)
+ {
+ /* Check the parameters */
+ assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
+
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+
+ if (hipcc->State == HAL_IPCC_STATE_RESET)
+ {
+ /* Init the low level hardware : CLOCK, NVIC */
+ HAL_IPCC_MspInit(hipcc);
+ }
+
+ /* Reset all registers of the current cpu to default state */
+ IPCC_Reset_Register(currentInstance);
+
+ /* Activate the interrupts */
+ currentInstance->CR |= (IPCC_CR_RXOIE | IPCC_CR_TXFIE);
+
+ /* Clear callback pointers */
+ IPCC_SetDefaultCallbacks(hipcc);
+
+ /* Reset all callback notification request */
+ hipcc->callbackRequest = 0;
+
+ hipcc->State = HAL_IPCC_STATE_READY;
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+
+ return err;
+}
+
+/**
+ * @brief DeInitialize the IPCC peripheral.
+ * @param hipcc IPCC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IPCC_DeInit(IPCC_HandleTypeDef *hipcc)
+{
+ HAL_StatusTypeDef err = HAL_OK;
+
+ /* Check the IPCC handle allocation */
+ if (hipcc != NULL)
+ {
+ assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+
+ /* Set the state to busy */
+ hipcc->State = HAL_IPCC_STATE_BUSY;
+
+ /* Reset all registers of the current cpu to default state */
+ IPCC_Reset_Register(currentInstance);
+
+ /* Clear callback pointers */
+ IPCC_SetDefaultCallbacks(hipcc);
+
+ /* Reset all callback notification request */
+ hipcc->callbackRequest = 0;
+
+ /* DeInit the low level hardware : CLOCK, NVIC */
+ HAL_IPCC_MspDeInit(hipcc);
+
+ hipcc->State = HAL_IPCC_STATE_RESET;
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+
+ return err;
+}
+
+/**
+ * @brief Initialize the IPCC MSP.
+ * @param hipcc IPCC handle
+ * @retval None
+ */
+__weak void HAL_IPCC_MspInit(IPCC_HandleTypeDef *hipcc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hipcc);
+
+ /* NOTE : This function should not be modified. When the callback is needed
+ the HAL_IPCC_MspInit should be implemented in the user file
+ */
+}
+
+/**
+ * @brief IPCC MSP DeInit
+ * @param hipcc IPCC handle
+ * @retval None
+ */
+__weak void HAL_IPCC_MspDeInit(IPCC_HandleTypeDef *hipcc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hipcc);
+
+ /* NOTE : This function should not be modified. When the callback is needed
+ the HAL_IPCC_MspDeInit should be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup IPCC_Exported_Functions_Group2
+ * @brief Configuration, notification and Irq handling functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions to allow two MCU to communicate.
+
+ (#) For a given channel (from 0 to IPCC_CHANNEL_NUMBER), for a given direction
+ IPCC_CHANNEL_DIR_TX or IPCC_CHANNEL_DIR_RX, you can choose to communicate
+ in polling mode or in interrupt mode using IPCC.
+ By default, the IPCC HAL driver handle the communication in polling mode.
+ By setting a callback for a channel/direction, this communication use
+ the interrupt mode.
+
+ (#) Polling mode:
+ (++) To transmit information, use HAL_IPCC_NotifyCPU() with
+ IPCC_CHANNEL_DIR_TX. To know when the other processor has handled
+ the notification, poll the communication using HAL_IPCC_NotifyCPU
+ with IPCC_CHANNEL_DIR_TX.
+
+ (++) To receive information, poll the status of the communication with
+ HAL_IPCC_GetChannelStatus with IPCC_CHANNEL_DIR_RX. To notify the other
+ processor that the information has been received, use HAL_IPCC_NotifyCPU
+ with IPCC_CHANNEL_DIR_RX.
+
+ (#) Interrupt mode:
+ (++) Configure a callback for the channel and the direction using HAL_IPCC_ConfigChannel().
+ This callback will be triggered under interrupt.
+
+ (++) To transmit information, use HAL_IPCC_NotifyCPU() with
+ IPCC_CHANNEL_DIR_TX. The callback configured with HAL_IPCC_ConfigChannel() and
+ IPCC_CHANNEL_DIR_TX will be triggered once the communication has been handled by the
+ other processor.
+
+ (++) To receive information, the callback configured with HAL_IPCC_ConfigChannel() and
+ IPCC_CHANNEL_DIR_RX will be triggered on reception of a communication.To notify the other
+ processor that the information has been received, use HAL_IPCC_NotifyCPU
+ with IPCC_CHANNEL_DIR_RX.
+
+ (++) HAL_IPCC_TX_IRQHandler must be added to the IPCC TX IRQHandler
+
+ (++) HAL_IPCC_RX_IRQHandler must be added to the IPCC RX IRQHandler
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Activate the callback notification on receive/transmit interrupt
+ * @param hipcc IPCC handle
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ * @param cb Interrupt callback
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IPCC_ActivateNotification(IPCC_HandleTypeDef *hipcc,
+ uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir,
+ ChannelCb cb)
+{
+ HAL_StatusTypeDef err = HAL_OK;
+
+ /* Check the IPCC handle allocation */
+ if (hipcc != NULL)
+ {
+ /* Check the parameters */
+ assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
+
+ /* Check IPCC state */
+ if (hipcc->State == HAL_IPCC_STATE_READY)
+ {
+ /* Set callback and register masking information */
+ if (ChannelDir == IPCC_CHANNEL_DIR_TX)
+ {
+ hipcc->ChannelCallbackTx[ChannelIndex] = cb;
+ hipcc->callbackRequest |= (IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+ else
+ {
+ hipcc->ChannelCallbackRx[ChannelIndex] = cb;
+ hipcc->callbackRequest |= (IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+
+ /* Unmask only the channels in reception (Transmission channel mask/unmask is done in HAL_IPCC_NotifyCPU) */
+ if (ChannelDir == IPCC_CHANNEL_DIR_RX)
+ {
+ IPCC_UnmaskInterrupt(ChannelIndex, ChannelDir);
+ }
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+ return err;
+}
+
+/**
+ * @brief Remove the callback notification on receive/transmit interrupt
+ * @param hipcc IPCC handle
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IPCC_DeActivateNotification(IPCC_HandleTypeDef *hipcc,
+ uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ HAL_StatusTypeDef err = HAL_OK;
+
+ /* Check the IPCC handle allocation */
+ if (hipcc != NULL)
+ {
+ /* Check the parameters */
+ assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
+
+ /* Check IPCC state */
+ if (hipcc->State == HAL_IPCC_STATE_READY)
+ {
+ /* Set default callback and register masking information */
+ if (ChannelDir == IPCC_CHANNEL_DIR_TX)
+ {
+ hipcc->ChannelCallbackTx[ChannelIndex] = HAL_IPCC_TxCallback;
+ hipcc->callbackRequest &= ~(IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+ else
+ {
+ hipcc->ChannelCallbackRx[ChannelIndex] = HAL_IPCC_RxCallback;
+ hipcc->callbackRequest &= ~(IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+
+ /* Mask the interrupt */
+ IPCC_MaskInterrupt(ChannelIndex, ChannelDir);
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+ return err;
+}
+
+/**
+ * @brief Get state of IPCC channel
+ * @param hipcc IPCC handle
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ * @retval Channel status
+ */
+IPCC_CHANNELStatusTypeDef HAL_IPCC_GetChannelStatus(IPCC_HandleTypeDef const *const hipcc,
+ uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ uint32_t channel_state;
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+ IPCC_CommonTypeDef *otherInstance = IPCC_C2;
+
+ /* Check the parameters */
+ assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
+
+ /* Read corresponding channel depending of the MCU and the direction */
+ if (ChannelDir == IPCC_CHANNEL_DIR_TX)
+ {
+ channel_state = (currentInstance->SR) & (IPCC_SR_CH1F_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+ else
+ {
+ channel_state = (otherInstance->SR) & (IPCC_SR_CH1F_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+
+ return (channel_state == 0UL) ? IPCC_CHANNEL_STATUS_FREE : IPCC_CHANNEL_STATUS_OCCUPIED ;
+}
+
+/**
+ * @brief Notify remote processor
+ * @param hipcc IPCC handle
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_IPCC_NotifyCPU(IPCC_HandleTypeDef const *const hipcc,
+ uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ HAL_StatusTypeDef err = HAL_OK;
+ uint32_t mask;
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+
+ /* Check the parameters */
+ assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
+
+ /* Check if IPCC is initialized */
+ if (hipcc->State == HAL_IPCC_STATE_READY)
+ {
+ /* For IPCC_CHANNEL_DIR_TX, set the status. For IPCC_CHANNEL_DIR_RX, clear the status */
+ currentInstance->SCR |= ((ChannelDir == IPCC_CHANNEL_DIR_TX) ? IPCC_SCR_CH1S :
+ IPCC_SCR_CH1C)
+ << (ChannelIndex & CHANNEL_INDEX_MASK);
+
+ /* Unmask interrupt if the callback is requested */
+ mask = ((ChannelDir == IPCC_CHANNEL_DIR_TX) ? IPCC_MR_CH1FM_Msk :
+ IPCC_MR_CH1OM_Msk) << (ChannelIndex & CHANNEL_INDEX_MASK);
+ if ((hipcc->callbackRequest & mask) == mask)
+ {
+ IPCC_UnmaskInterrupt(ChannelIndex, ChannelDir);
+ }
+ }
+ else
+ {
+ err = HAL_ERROR;
+ }
+
+ return err;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup IPCC_IRQ_Handler_and_Callbacks
+ * @{
+ */
+
+/**
+ * @brief This function handles IPCC Tx Free interrupt request.
+ * @param hipcc IPCC handle
+ * @retval None
+ */
+void HAL_IPCC_TX_IRQHandler(IPCC_HandleTypeDef *const hipcc)
+{
+ uint32_t irqmask;
+ uint32_t bit_pos;
+ uint32_t ch_count = 0U;
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+
+ /* check the Tx free channels which are not masked */
+ irqmask = ~(currentInstance->MR) & IPCC_ALL_TX_BUF;
+ irqmask = irqmask & ~(currentInstance->SR << IPCC_MR_CH1FM_Pos);
+
+ while (irqmask != 0UL) /* if several bits are set, it loops to serve all of them */
+ {
+ bit_pos = 1UL << (IPCC_MR_CH1FM_Pos + (ch_count & CHANNEL_INDEX_MASK));
+
+ if ((irqmask & bit_pos) != 0U)
+ {
+ /* mask the channel Free interrupt */
+ currentInstance->MR |= bit_pos;
+ if (hipcc->ChannelCallbackTx[ch_count] != NULL)
+ {
+ hipcc->ChannelCallbackTx[ch_count](hipcc, ch_count, IPCC_CHANNEL_DIR_TX);
+ }
+ irqmask = irqmask & ~(bit_pos);
+ }
+ ch_count++;
+ }
+}
+
+/**
+ * @brief This function handles IPCC Rx Occupied interrupt request.
+ * @param hipcc : IPCC handle
+ * @retval None
+ */
+void HAL_IPCC_RX_IRQHandler(IPCC_HandleTypeDef *const hipcc)
+{
+ uint32_t irqmask;
+ uint32_t bit_pos;
+ uint32_t ch_count = 0U;
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+ IPCC_CommonTypeDef *otherInstance = IPCC_C2;
+
+ /* check the Rx occupied channels which are not masked */
+ irqmask = ~(currentInstance->MR) & IPCC_ALL_RX_BUF;
+ irqmask = irqmask & otherInstance->SR;
+
+ while (irqmask != 0UL) /* if several bits are set, it loops to serve all of them */
+ {
+ bit_pos = 1UL << (ch_count & CHANNEL_INDEX_MASK);
+
+ if ((irqmask & bit_pos) != 0U)
+ {
+ /* mask the channel occupied interrupt */
+ currentInstance->MR |= bit_pos;
+ if (hipcc->ChannelCallbackRx[ch_count] != NULL)
+ {
+ hipcc->ChannelCallbackRx[ch_count](hipcc, ch_count, IPCC_CHANNEL_DIR_RX);
+ }
+ irqmask = irqmask & ~(bit_pos);
+ }
+ ch_count++;
+ }
+}
+
+/**
+ * @brief Rx occupied callback
+ * @param hipcc IPCC handle
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ */
+__weak void HAL_IPCC_RxCallback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hipcc);
+ UNUSED(ChannelIndex);
+ UNUSED(ChannelDir);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IPCC_RxCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx free callback
+ * @param hipcc IPCC handle
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ */
+__weak void HAL_IPCC_TxCallback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hipcc);
+ UNUSED(ChannelIndex);
+ UNUSED(ChannelDir);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_IPCC_TxCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup IPCC_Exported_Functions_Group3
+ * @brief IPCC Peripheral State and Error functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection permit to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the IPCC handle state.
+ * @param hipcc IPCC handle
+ * @retval IPCC handle state
+ */
+HAL_IPCC_StateTypeDef HAL_IPCC_GetState(IPCC_HandleTypeDef const *const hipcc)
+{
+ return hipcc->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup IPCC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Mask IPCC interrupts.
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ */
+void IPCC_MaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+ if (ChannelDir == IPCC_CHANNEL_DIR_TX)
+ {
+ /* Mask interrupt */
+ currentInstance->MR |= (IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+ else
+ {
+ /* Mask interrupt */
+ currentInstance->MR |= (IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+}
+/**
+ * @brief Unmask IPCC interrupts.
+ * @param ChannelIndex Channel number
+ * This parameter can be one of the following values:
+ * @arg IPCC_CHANNEL_1: IPCC Channel 1
+ * @arg IPCC_CHANNEL_2: IPCC Channel 2
+ * @arg IPCC_CHANNEL_3: IPCC Channel 3
+ * @arg IPCC_CHANNEL_4: IPCC Channel 4
+ * @arg IPCC_CHANNEL_5: IPCC Channel 5
+ * @arg IPCC_CHANNEL_6: IPCC Channel 6
+ * @param ChannelDir Channel direction
+ */
+void IPCC_UnmaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
+{
+ IPCC_CommonTypeDef *currentInstance = IPCC_C1;
+ if (ChannelDir == IPCC_CHANNEL_DIR_TX)
+ {
+ /* Unmask interrupt */
+ currentInstance->MR &= ~(IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+ else
+ {
+ /* Unmask interrupt */
+ currentInstance->MR &= ~(IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_MASK));
+ }
+}
+
+/**
+ * @brief Reset all callbacks of the handle to NULL.
+ * @param hipcc IPCC handle
+ */
+void IPCC_SetDefaultCallbacks(IPCC_HandleTypeDef *hipcc)
+{
+ uint32_t i;
+ /* Set all callbacks to default */
+ for (i = 0; i < IPCC_CHANNEL_NUMBER; i++)
+ {
+ hipcc->ChannelCallbackRx[i] = HAL_IPCC_RxCallback;
+ hipcc->ChannelCallbackTx[i] = HAL_IPCC_TxCallback;
+ }
+}
+
+/**
+ * @brief Reset IPCC register to default value for the concerned instance.
+ * @param Instance pointer to register
+ */
+void IPCC_Reset_Register(IPCC_CommonTypeDef *Instance)
+{
+ /* Disable RX and TX interrupts */
+ Instance->CR = 0x00000000U;
+
+ /* Mask RX and TX interrupts */
+ Instance->MR = (IPCC_ALL_TX_BUF | IPCC_ALL_RX_BUF);
+
+ /* Clear RX status */
+ Instance->SCR = IPCC_ALL_RX_BUF;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_IPCC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* IPCC */
+
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c
new file mode 100644
index 0000000..baeddf4
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c
@@ -0,0 +1,742 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_pwr.c
+ * @author MCD Application Team
+ * @brief PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Power Controller (PWR) peripheral:
+ * + Initialization/de-initialization functions
+ * + Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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 "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup PWR
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup PWR_Private_Defines
+ * @{
+ */
+
+/** @defgroup PWR_Register_Reset_Values PWR Register Reset Values
+ * @{
+ */
+/* Definitions of PWR registers reset value */
+#define PWR_CR1_RESET_VALUE (0x00000200U)
+#define PWR_CR2_RESET_VALUE (0x00000000U)
+#define PWR_CR3_RESET_VALUE (0x00008000U)
+#define PWR_CR4_RESET_VALUE (0x00000000U)
+#define PWR_CR5_RESET_VALUE (0x00004204U)
+#define PWR_PUCRA_RESET_VALUE (0x00000000U)
+#define PWR_PDCRA_RESET_VALUE (0x00000000U)
+#define PWR_PUCRB_RESET_VALUE (0x00000000U)
+#define PWR_PDCRB_RESET_VALUE (0x00000000U)
+#define PWR_PUCRC_RESET_VALUE (0x00000000U)
+#define PWR_PDCRC_RESET_VALUE (0x00000000U)
+#define PWR_PUCRD_RESET_VALUE (0x00000000U)
+#define PWR_PDCRD_RESET_VALUE (0x00000000U)
+#define PWR_PUCRE_RESET_VALUE (0x00000000U)
+#define PWR_PDCRE_RESET_VALUE (0x00000000U)
+#define PWR_PUCRH_RESET_VALUE (0x00000000U)
+#define PWR_PDCRH_RESET_VALUE (0x00000000U)
+#define PWR_C2CR1_RESET_VALUE (0x00000000U)
+#define PWR_C2CR3_RESET_VALUE (0x00008000U)
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup PWR_Exported_Functions PWR Exported Functions
+ * @{
+ */
+
+/** @addtogroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitialize the HAL PWR peripheral registers to their default reset values.
+ * @retval None
+ */
+void HAL_PWR_DeInit(void)
+{
+ /* Apply reset values to all PWR registers */
+ /* Note: Update of each register required since PWR global reset is not */
+ /* available at RCC level on this STM32 series. */
+ LL_PWR_WriteReg(CR1, PWR_CR1_RESET_VALUE);
+ LL_PWR_WriteReg(CR2, PWR_CR2_RESET_VALUE);
+ LL_PWR_WriteReg(CR3, PWR_CR3_RESET_VALUE);
+ LL_PWR_WriteReg(CR4, PWR_CR4_RESET_VALUE);
+ LL_PWR_WriteReg(CR5, PWR_CR5_RESET_VALUE);
+ LL_PWR_WriteReg(PUCRA, PWR_PUCRA_RESET_VALUE);
+ LL_PWR_WriteReg(PDCRA, PWR_PDCRA_RESET_VALUE);
+ LL_PWR_WriteReg(PUCRB, PWR_PUCRB_RESET_VALUE);
+ LL_PWR_WriteReg(PDCRB, PWR_PDCRB_RESET_VALUE);
+ LL_PWR_WriteReg(PUCRC, PWR_PUCRC_RESET_VALUE);
+ LL_PWR_WriteReg(PDCRC, PWR_PDCRC_RESET_VALUE);
+#if defined(GPIOD)
+ LL_PWR_WriteReg(PUCRD, PWR_PUCRD_RESET_VALUE);
+ LL_PWR_WriteReg(PDCRD, PWR_PDCRD_RESET_VALUE);
+#endif /* GPIOD */
+ LL_PWR_WriteReg(PUCRE, PWR_PUCRE_RESET_VALUE);
+ LL_PWR_WriteReg(PDCRE, PWR_PDCRE_RESET_VALUE);
+ LL_PWR_WriteReg(PUCRH, PWR_PUCRH_RESET_VALUE);
+ LL_PWR_WriteReg(PDCRH, PWR_PDCRH_RESET_VALUE);
+ LL_PWR_WriteReg(C2CR1, PWR_C2CR1_RESET_VALUE);
+ LL_PWR_WriteReg(C2CR3, PWR_C2CR3_RESET_VALUE);
+
+ /* Clear all flags */
+#if defined(PWR_CR3_E802A) && defined(PWR_CR5_SMPSEN)
+ LL_PWR_WriteReg(SCR,
+ LL_PWR_SCR_CC2HF
+ | LL_PWR_SCR_CBLEAF
+ | LL_PWR_SCR_CCRPEF
+ | LL_PWR_SCR_C802AF
+ | LL_PWR_SCR_C802WUF
+ | LL_PWR_SCR_CBLEWUF
+ | LL_PWR_SCR_CBORHF
+ | LL_PWR_SCR_CSMPSFBF
+ | LL_PWR_SCR_CWUF);
+#elif defined(PWR_CR3_E802A)
+ LL_PWR_WriteReg(SCR,
+ LL_PWR_SCR_CC2HF
+ | LL_PWR_SCR_CBLEAF
+ | LL_PWR_SCR_CCRPEF
+ | LL_PWR_SCR_C802AF
+ | LL_PWR_SCR_C802WUF
+ | LL_PWR_SCR_CBLEWUF
+ | LL_PWR_SCR_CWUF);
+#elif defined(PWR_CR5_SMPSEN)
+ LL_PWR_WriteReg(SCR,
+ LL_PWR_SCR_CC2HF
+ | LL_PWR_SCR_CBLEAF
+ | LL_PWR_SCR_CCRPEF
+ | LL_PWR_SCR_CBLEWUF
+ | LL_PWR_SCR_CBORHF
+ | LL_PWR_SCR_CSMPSFBF
+ | LL_PWR_SCR_CWUF);
+#else
+ LL_PWR_WriteReg(SCR,
+ LL_PWR_SCR_CC2HF
+ | LL_PWR_SCR_CBLEAF
+ | LL_PWR_SCR_CCRPEF
+ | LL_PWR_SCR_CBLEWUF
+ | LL_PWR_SCR_CWUF);
+#endif
+
+ LL_PWR_WriteReg(EXTSCR,
+ LL_PWR_EXTSCR_CCRPF
+ | LL_PWR_EXTSCR_C2CSSF
+ | LL_PWR_EXTSCR_C1CSSF
+ );
+}
+
+
+/**
+ * @brief Enable access to the backup domain
+ * (RTC registers, RTC backup data registers).
+ * @note After reset, the backup domain is protected against
+ * possible unwanted write accesses.
+ * @note RTCSEL that sets the RTC clock source selection is in the RTC back-up domain.
+ * In order to set or modify the RTC clock, the backup domain access must be
+ * disabled.
+ * @note LSEON bit that switches on and off the LSE crystal belongs as well to the
+ * back-up domain.
+ * @retval None
+ */
+void HAL_PWR_EnableBkUpAccess(void)
+{
+ SET_BIT(PWR->CR1, PWR_CR1_DBP);
+}
+
+/**
+ * @brief Disable access to the backup domain
+ * (RTC registers, RTC backup data registers).
+ * @retval None
+ */
+void HAL_PWR_DisableBkUpAccess(void)
+{
+ CLEAR_BIT(PWR->CR1, PWR_CR1_DBP);
+}
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup PWR_Exported_Functions_Group2 Peripheral Control functions
+ * @brief Low Power modes configuration functions
+ *
+@verbatim
+
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+
+ [..]
+ *** PVD configuration ***
+ =========================
+ [..]
+ (+) The PVD is used to monitor the VDD power supply by comparing it to a
+ threshold selected by the PVD Level (PLS[2:0] bits in PWR_CR2 register).
+ (+) PVDO flag is available to indicate if VDD/VDDA is higher or lower
+ than the PVD threshold. This event is internally connected to the EXTI
+ line16 and can generate an interrupt if enabled. This is done through
+ __HAL_PVD_EXTI_ENABLE_IT() macro.
+ (+) The PVD is stopped in Standby mode.
+
+ *** WakeUp pin configuration ***
+ ================================
+ [..]
+ (+) WakeUp pins are used to wakeup the system from Standby mode or Shutdown mode.
+ The polarity of these pins can be set to configure event detection on high
+ level (rising edge) or low level (falling edge).
+
+ *** Low Power modes configuration ***
+ =====================================
+ [..]
+ The devices feature 8 low-power modes:
+
+ (+) Low-power Run mode: core and peripherals are running, main regulator off, low power regulator on.
+
+ (+) Sleep mode: Cortex-M4 core stopped, peripherals kept running, main and low power regulators on.
+ (+) Low-power Sleep mode: Cortex-M4 core stopped, peripherals kept running, main regulator off, low power regulator on.
+
+ (+) Stop 0 mode: all clocks are stopped except LSI and LSE, main and low power regulators on.
+ (+) Stop 1 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on.
+ (+) Stop 2 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on, reduced set of waking up IPs compared to Stop 1 mode.
+
+ (+) Standby mode with SRAM2a: all clocks are stopped except LSI and LSE, SRAM2a content preserved, main regulator off, low power regulator on.
+ Note: On devices STM32WB15xx, STM32WB10xx, STM32WB1Mxx retention is extended to SRAM1, SRAM2a, SRAM2b.
+ (+) Standby mode without SRAM2a: all clocks are stopped except LSI and LSE, main and low power regulators off.
+
+ (+) Shutdown mode: all clocks are stopped except LSE, main and low power regulators off.
+
+
+ *** Low-power run mode ***
+ ==========================
+ [..]
+ (+) Entry: (from main run mode)
+ (++) set LPR bit with HAL_PWREx_EnableLowPowerRunMode() API after having decreased the system clock below 2 MHz.
+ (+) Exit:
+ (++) clear LPR bit then wait for REGLP bit to be reset with HAL_PWREx_DisableLowPowerRunMode() API. Only
+ then can the system clock frequency be increased above 2 MHz.
+
+ *** Sleep mode / Low-power sleep mode ***
+ =========================================
+ [..]
+ (+) Entry:
+ The Sleep mode / Low-power Sleep mode is entered thru HAL_PWR_EnterSLEEPMode() API
+ in specifying whether or not the regulator is forced to low-power mode and if exit is interrupt or event-triggered.
+ (++) PWR_MAINREGULATOR_ON: Sleep mode (regulator in main mode).
+ (++) PWR_LOWPOWERREGULATOR_ON: Low-power sleep (regulator in low power mode).
+ In the latter case, the system clock frequency must have been decreased below 2 MHz beforehand.
+ (++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
+ (++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
+
+ (+) WFI Exit:
+ (++) Any peripheral interrupt acknowledged by the nested vectored interrupt
+ controller (NVIC) or any wake-up event.
+
+ (+) WFE Exit:
+ (++) Any wake-up event such as an EXTI line configured in event mode.
+
+ [..] When exiting the Low-power sleep mode by issuing an interrupt or a wakeup event,
+ the MCU is in Low-power Run mode.
+
+ *** Stop 0, Stop 1 and Stop 2 modes ***
+ ===============================
+ [..]
+ (+) Entry:
+ The Stop 0, Stop 1 or Stop 2 modes are entered thru the following API's:
+ (++) HAL_PWREx_EnterSTOP0Mode() for mode 0, HAL_PWREx_EnterSTOP1Mode() for mode 1, HAL_PWREx_EnterSTOP2Mode() for mode 2
+ or for porting reasons HAL_PWR_EnterSTOPMode().
+ Note: Low power Stop2 mode is not available on devices STM32WB15xx, STM32WB10xx, STM32WB1Mxx.
+
+ (+) Regulator setting (applicable to HAL_PWR_EnterSTOPMode() only):
+ (++) PWR_MAINREGULATOR_ON: Regulator in main mode (STOP0 mode)
+ (++) PWR_LOWPOWERREGULATOR_ON: Regulator in low-power mode (STOP1 mode)
+ (+) Exit (interrupt or event-triggered, specified when entering STOP mode):
+ (++) PWR_STOPENTRY_WFI: enter Stop mode with WFI instruction
+ (++) PWR_STOPENTRY_WFE: enter Stop mode with WFE instruction
+ (+) WFI Exit:
+ (++) Any EXTI Line (Internal or External) configured in Interrupt mode.
+ (++) Some specific communication peripherals (USART, LPUART, I2C) interrupts
+ when programmed in wakeup mode.
+ (+) WFE Exit:
+ (++) Any EXTI Line (Internal or External) configured in Event mode.
+
+ [..]
+ When exiting Stop 0 and Stop 1 modes, the MCU is either in Run mode or in Low-power Run mode
+ depending on the LPR bit setting.
+ When exiting Stop 2 mode, the MCU is in Run mode.
+
+ *** Standby mode ***
+ ====================
+ [..] The Standby mode offers two options:
+ (+) option a) all clocks off except LSI and LSE, RRS bit set (keeps voltage regulator in low power mode).
+ SRAM and registers contents are lost except for the SRAM2 content, the RTC registers, RTC backup registers
+ and Standby circuitry.
+ (+) option b) all clocks off except LSI and LSE, RRS bit cleared (voltage regulator then disabled).
+ SRAM and register contents are lost except for the RTC registers, RTC backup registers
+ and Standby circuitry.
+
+ (++) Entry:
+ (+++) The Standby mode is entered thru HAL_PWR_EnterSTANDBYMode() API.
+ SRAM1 and register contents are lost except for registers in the Backup domain and
+ Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register.
+ To enable this feature, the user can resort to HAL_PWREx_EnableBKRAMContentRetention() API
+ to set RRS bit.
+ (++) Exit:
+ (+++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event,
+ external reset in NRST pin, IWDG reset.
+ [..] After waking up from Standby mode, program execution restarts in the same way as after a Reset.
+
+
+ *** Shutdown mode ***
+ ======================
+ [..]
+ In Shutdown mode,
+ voltage regulator is disabled, all clocks are off except LSE, RRS bit is cleared.
+ SRAM and registers contents are lost except for backup domain registers.
+ (+) Entry:
+ The Shutdown mode is entered thru HAL_PWREx_EnterSHUTDOWNMode() API.
+ (+) Exit:
+ (++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event,
+ external reset in NRST pin.
+ [..] After waking up from Shutdown mode, program execution restarts in the same way as after a Reset.
+
+
+ *** Auto-wakeup (AWU) from low-power mode ***
+ =============================================
+ [..]
+ The MCU can be woken up from low-power mode by an RTC Alarm event, an RTC
+ Wakeup event, a tamper event or a time-stamp event, without depending on
+ an external interrupt (Auto-wakeup mode).
+
+ (+) RTC auto-wakeup (AWU) from the Stop, Standby and Shutdown modes
+
+
+ (++) To wake up from the Stop mode with an RTC alarm event, it is necessary to
+ configure the RTC to generate the RTC alarm using the HAL_RTC_SetAlarm_IT() function.
+
+ (++) To wake up from the Stop mode with an RTC Tamper or time stamp event, it
+ is necessary to configure the RTC to detect the tamper or time stamp event using the
+ HAL_RTCEx_SetTimeStamp_IT() or HAL_RTCEx_SetTamper_IT() functions.
+
+ (++) To wake up from the Stop mode with an RTC WakeUp event, it is necessary to
+ configure the RTC to generate the RTC WakeUp event using the HAL_RTCEx_SetWakeUpTimer_IT() function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the voltage threshold detected by the Power Voltage Detector (PVD).
+ * @param sConfigPVD pointer to a PWR_PVDTypeDef structure that contains the PVD
+ * configuration information.
+ * @note Refer to the electrical characteristics of your device datasheet for
+ * more details about the voltage thresholds corresponding to each
+ * detection level.
+ * @note If "sConfigPVD->Mode" is set to PVD_MODE_IT,
+ * wake-up target is set by default to wake-up target CPU1.
+ * To select wake-up target to CPU2, additional configuration must be
+ * performed using macro "__HAL_PWR_PVD_EXTIC2_ENABLE_IT()"
+ * (and optionally, to select CPU2 only (not both CPU1 and CPU2):
+ * "__HAL_PWR_PVD_EXTI_DISABLE_IT()").
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_PVD_LEVEL(sConfigPVD->PVDLevel));
+ assert_param(IS_PWR_PVD_MODE(sConfigPVD->Mode));
+
+ /* Set PLS bits according to PVDLevel value */
+ MODIFY_REG(PWR->CR2, PWR_CR2_PLS, sConfigPVD->PVDLevel);
+
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+
+ /* Note: On STM32WB series, power PVD event is not available on AIEC lines */
+ /* (only interruption is available through AIEC line 16). */
+ __HAL_PWR_PVD_EXTI_DISABLE_IT(); /*CPU1*/
+ __HAL_PWR_PVD_EXTIC2_DISABLE_IT(); /*CPU2*/
+
+ __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE();
+ __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE();
+
+ /* Configure interrupt mode */
+ if ((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT)
+ {
+ /* Set CPU1 as wakeup target */
+ __HAL_PWR_PVD_EXTI_ENABLE_IT();
+ }
+
+ /* Configure the edge */
+ if ((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if ((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE();
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables the Power Voltage Detector(PVD).
+ * @retval None
+ */
+void HAL_PWR_EnablePVD(void)
+{
+ /* Enable the power voltage detector */
+ SET_BIT(PWR->CR2, PWR_CR2_PVDE);
+}
+
+/**
+ * @brief Disables the Power Voltage Detector(PVD).
+ * @retval None
+ */
+void HAL_PWR_DisablePVD(void)
+{
+ /* Disable the power voltage detector */
+ CLEAR_BIT(PWR->CR2, PWR_CR2_PVDE);
+}
+
+
+/**
+ * @brief Enable the WakeUp PINx functionality.
+ * @param WakeUpPinPolarity Specifies which Wake-Up pin to enable.
+ * This parameter can be one of the following legacy values which set the default polarity
+ * i.e. detection on high level (rising edge):
+ * @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5
+ *
+ * or one of the following value where the user can explicitly specify the enabled pin and
+ * the chosen polarity:
+ * @arg @ref PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW
+ * @arg @ref PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW
+ * @arg @ref PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW
+ * @arg @ref PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW
+ * @arg @ref PWR_WAKEUP_PIN5_HIGH or PWR_WAKEUP_PIN5_LOW
+ * @note PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent.
+ * @retval None
+ */
+void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity)
+{
+ assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinPolarity));
+
+ /* Specifies the Wake-Up pin polarity for the event detection
+ (rising or falling edge) */
+ MODIFY_REG(PWR->CR4, (PWR_CR3_EWUP & WakeUpPinPolarity), (WakeUpPinPolarity >> PWR_WUP_POLARITY_SHIFT));
+
+ /* Enable wake-up pin */
+ SET_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinPolarity));
+}
+
+/**
+ * @brief Disable the WakeUp PINx functionality.
+ * @param WakeUpPinx Specifies the Power Wake-Up pin to disable.
+ * This parameter can be one of the following values:
+ * @arg PWR_WAKEUP_PIN1: An event on PA0 PIN wakes-up the system from Standby mode.
+ * @arg PWR_WAKEUP_PIN2: An event on PC13 PIN wakes-up the system from Standby mode.
+ * @arg PWR_WAKEUP_PIN3: An event on PC12 PIN wakes-up the system from Standby mode.
+ * @arg PWR_WAKEUP_PIN4: An event on PA2 PIN wakes-up the system from Standby mode.
+ * @arg PWR_WAKEUP_PIN5: An event on PC5 PIN wakes-up the system from Standby mode.
+ * @retval None
+ */
+void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx)
+{
+ assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx));
+
+ CLEAR_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinx));
+}
+
+/**
+ * @brief Enter Sleep or Low-power Sleep mode.
+ * @note In Sleep/Low-power Sleep mode, all I/O pins keep the same state as in Run mode.
+ * @param Regulator Specifies the regulator state in Sleep/Low-power Sleep mode.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_MAINREGULATOR_ON Sleep mode (regulator in main mode)
+ * @arg @ref PWR_LOWPOWERREGULATOR_ON Low-power Sleep mode (regulator in low-power mode)
+ * @note Low-power Sleep mode is entered from Low-power Run mode. Therefore, if not yet
+ * in Low-power Run mode before calling HAL_PWR_EnterSLEEPMode() with Regulator set
+ * to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the
+ * Flash in power-down mode in setting the SLEEP_PD bit in FLASH_ACR register.
+ * Additionally, the clock frequency must be reduced below 2 MHz.
+ * Setting SLEEP_PD in FLASH_ACR then appropriately reducing the clock frequency must
+ * be done before calling HAL_PWR_EnterSLEEPMode() API.
+ * @note When exiting Low-power Sleep mode, the MCU is in Low-power Run mode. To move in
+ * Run mode, the user must resort to HAL_PWREx_DisableLowPowerRunMode() API.
+ * @param SLEEPEntry Specifies if Sleep mode is entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_SLEEPENTRY_WFI enter Sleep or Low-power Sleep mode with WFI instruction
+ * @arg @ref PWR_SLEEPENTRY_WFE enter Sleep or Low-power Sleep mode with WFE instruction
+ * @note When WFI entry is used, tick interrupt have to be disabled if not desired as
+ * the interrupt wake up source.
+ * @retval None
+ */
+void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_REGULATOR(Regulator));
+ assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry));
+
+ /* Set Regulator parameter */
+ if (Regulator == PWR_MAINREGULATOR_ON)
+ {
+ /* If in low-power run mode at this point, exit it */
+ if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))
+ {
+ if (HAL_PWREx_DisableLowPowerRunMode() != HAL_OK)
+ {
+ return ;
+ }
+ }
+ /* Regulator now in main mode. */
+ }
+ else
+ {
+ /* If in run mode, first move to low-power run mode.
+ The system clock frequency must be below 2 MHz at this point. */
+ if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF) == RESET)
+ {
+ HAL_PWREx_EnableLowPowerRunMode();
+ }
+ }
+
+ /* Clear SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select SLEEP mode entry -------------------------------------------------*/
+ if (SLEEPEntry == PWR_SLEEPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+}
+
+
+/**
+ * @brief Enter Stop mode
+ * @note This API is named HAL_PWR_EnterSTOPMode to ensure compatibility with legacy code running
+ * on devices where only "Stop mode" is mentioned with main or low power regulator ON.
+ * @note In Stop mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
+ * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
+ * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
+ * only to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * The voltage regulator can be configured either in normal (Stop 0) or low-power mode (Stop 1).
+ * @note When exiting Stop 0 or Stop 1 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @note When the voltage regulator operates in low power mode (Stop 1), an additional
+ * startup delay is incurred when waking up.
+ * By keeping the internal regulator ON during Stop mode (Stop 0), the consumption
+ * is higher although the startup time is reduced.
+ * @note Case of Stop0 mode with SMPS: Before entering Stop 0 mode with SMPS Step Down converter enabled,
+ * the HSI16 must be kept on by enabling HSI kernel clock (set HSIKERON register bit).
+ * @note According to system power policy, system entering in Stop mode
+ * is depending on other CPU power mode.
+ * @param Regulator Specifies the regulator state in Stop mode.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_MAINREGULATOR_ON Stop 0 mode (main regulator ON)
+ * @arg @ref PWR_LOWPOWERREGULATOR_ON Stop 1 mode (low power regulator ON)
+ * @param STOPEntry Specifies Stop 0, Stop 1 or Stop 2 mode is entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop 0 or Stop 1 mode with WFI instruction.
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop 0 or Stop 1 mode with WFE instruction.
+ * @retval None
+ */
+void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_REGULATOR(Regulator));
+
+ if (Regulator == PWR_LOWPOWERREGULATOR_ON)
+ {
+ HAL_PWREx_EnterSTOP1Mode(STOPEntry);
+ }
+ else
+ {
+ HAL_PWREx_EnterSTOP0Mode(STOPEntry);
+ }
+}
+
+
+/**
+ * @brief Enter Standby mode.
+ * @note In Standby mode, the PLL, the HSI, the MSI and the HSE oscillators are switched
+ * off. The voltage regulator is disabled, except when BKRAM content is preserved
+ * in which case the regulator is in low-power mode.
+ * SRAM and register contents are lost except for registers in the Backup domain and
+ * Standby circuitry. BKRAM content can be preserved if the bit RRS is set in PWR_CR3 register.
+ * To enable this feature, the user can resort to HAL_PWREx_EnableBKRAMContentRetention() API
+ * to set RRS bit.
+ * The BOR is available.
+ * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state.
+ * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() respectively enable Pull Up and
+ * Pull Down state, HAL_PWREx_DisableGPIOPullUp() and HAL_PWREx_DisableGPIOPullDown() disable the
+ * same.
+ * These states are effective in Standby mode only if APC bit is set through
+ * HAL_PWREx_EnablePullUpPullDownConfig() API.
+ * @note According to system power policy, system entering in Standby mode
+ * is depending on other CPU power mode.
+ * @retval None
+ */
+void HAL_PWR_EnterSTANDBYMode(void)
+{
+ /* Set Stand-by mode */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_STANDBY);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* This option is used to ensure that store operations are completed */
+#if defined (__CC_ARM)
+ __force_stores();
+#endif /* __CC_ARM */
+
+ /* Request Wait For Interrupt */
+ __WFI();
+
+ /* Following code is executed after wake up if system did not go to STANDBY
+ mode according to system power policy */
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+/**
+ * @brief Indicate Sleep-On-Exit when returning from Handler mode to Thread mode.
+ * @note Set SLEEPONEXIT bit of SCR register. When this bit is set, the processor
+ * re-enters SLEEP mode when an interruption handling is over.
+ * Setting this bit is useful when the processor is expected to run only on
+ * interruptions handling.
+ * @retval None
+ */
+void HAL_PWR_EnableSleepOnExit(void)
+{
+ /* Set SLEEPONEXIT bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
+}
+
+/**
+ * @brief Disable Sleep-On-Exit feature when returning from Handler mode to Thread mode.
+ * @note Clear SLEEPONEXIT bit of SCR register. When this bit is set, the processor
+ * re-enters SLEEP mode when an interruption handling is over.
+ * @retval None
+ */
+void HAL_PWR_DisableSleepOnExit(void)
+{
+ /* Clear SLEEPONEXIT bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
+}
+
+
+/**
+ * @brief Enable CORTEX M4 SEVONPEND bit.
+ * @note Set SEVONPEND bit of SCR register. When this bit is set, this causes
+ * WFE to wake up when an interrupt moves from inactive to pended.
+ * @retval None
+ */
+void HAL_PWR_EnableSEVOnPend(void)
+{
+ /* Set SEVONPEND bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
+}
+
+
+/**
+ * @brief Disable CORTEX M4 SEVONPEND bit.
+ * @note Clear SEVONPEND bit of SCR register. When this bit is set, this causes
+ * WFE to wake up when an interrupt moves from inactive to pended.
+ * @retval None
+ */
+void HAL_PWR_DisableSEVOnPend(void)
+{
+ /* Clear SEVONPEND bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
+}
+
+
+/**
+ * @brief PWR PVD interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWR_PVDCallback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ the HAL_PWR_PVDCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c
new file mode 100644
index 0000000..b39074d
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c
@@ -0,0 +1,1368 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_pwr_ex.c
+ * @author MCD Application Team
+ * @brief Extended PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Power Controller (PWR) peripheral:
+ * + Extended Initialization and de-initialization functions
+ * + Extended Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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 "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup PWREx
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup PWR_Extended_Private_Defines PWR Extended Private Defines
+ * @{
+ */
+#define PWR_PORTE_AVAILABLE_PINS (PWR_GPIO_BIT_4 | PWR_GPIO_BIT_3 | PWR_GPIO_BIT_2 | PWR_GPIO_BIT_1 | PWR_GPIO_BIT_0)
+#define PWR_PORTH_AVAILABLE_PINS (PWR_GPIO_BIT_3 | PWR_GPIO_BIT_1 | PWR_GPIO_BIT_0)
+
+/** @defgroup PWREx_TimeOut_Value PWR Extended Flag Setting Time Out Value
+ * @{
+ */
+#define PWR_FLAG_SETTING_DELAY_US 50U /*!< Time out value for REGLPF and VOSF flags setting */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup PWREx_Exported_Functions PWR Extended Exported Functions
+ * @{
+ */
+
+/** @addtogroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+
+@endverbatim
+ * @{
+ */
+
+
+#if defined(PWR_CR1_VOS)
+/**
+ * @brief Return Voltage Scaling Range.
+ * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_RANGE1 or PWR_REGULATOR_VOLTAGE_RANGE2)
+ */
+uint32_t HAL_PWREx_GetVoltageRange(void)
+{
+ return (PWR->CR1 & PWR_CR1_VOS);
+}
+
+/**
+ * @brief Configure the main internal regulator output voltage.
+ * @param VoltageScaling specifies the regulator output voltage to achieve
+ * a tradeoff between performance and power consumption.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode,
+ * typical output voltage at 1.2 V,
+ * system frequency up to 64 MHz.
+ * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode,
+ * typical output voltage at 1.0 V,
+ * system frequency up to 16 MHz.
+ * @note When moving from Range 1 to Range 2, the system frequency must be decreased to
+ * a value below 16 MHz before calling HAL_PWREx_ControlVoltageScaling() API.
+ * When moving from Range 2 to Range 1, the system frequency can be increased to
+ * a value up to 64 MHz after calling HAL_PWREx_ControlVoltageScaling() API.
+ * @note When moving from Range 2 to Range 1, the API waits for VOSF flag to be
+ * cleared before returning the status. If the flag is not cleared within
+ * 50 microseconds, HAL_TIMEOUT status is reported.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling)
+{
+ uint32_t wait_loop_index;
+
+ assert_param(IS_PWR_VOLTAGE_SCALING_RANGE(VoltageScaling));
+
+ /* If Set Range 1 */
+ if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ /* Set Range 1 */
+ MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /* Wait until VOSF is cleared */
+ wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000U));
+ while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U))
+ {
+ wait_loop_index--;
+ }
+ if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE2)
+ {
+ /* Set Range 2 */
+ MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2);
+ /* No need to wait for VOSF to be cleared for this transition */
+ }
+ }
+
+ return HAL_OK;
+}
+#endif /* PWR_CR1_VOS */
+
+/****************************************************************************/
+
+/**
+ * @brief Enable battery charging.
+ * When VDD is present, charge the external battery on VBAT thru an internal resistor.
+ * @param ResistorSelection specifies the resistor impedance.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_5 5 kOhms resistor
+ * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_1_5 1.5 kOhms resistor
+ * @retval None
+ */
+void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection)
+{
+ assert_param(IS_PWR_BATTERY_RESISTOR_SELECT(ResistorSelection));
+
+ /* Specify resistor selection */
+ MODIFY_REG(PWR->CR4, PWR_CR4_VBRS, ResistorSelection);
+
+ /* Enable battery charging */
+ SET_BIT(PWR->CR4, PWR_CR4_VBE);
+}
+
+/**
+ * @brief Disable battery charging.
+ * @retval None
+ */
+void HAL_PWREx_DisableBatteryCharging(void)
+{
+ CLEAR_BIT(PWR->CR4, PWR_CR4_VBE);
+}
+
+/****************************************************************************/
+#if defined(PWR_CR2_PVME1)
+/**
+ * @brief Enable VDDUSB supply.
+ * @note Remove VDDUSB electrical and logical isolation, once VDDUSB supply is present.
+ * @retval None
+ */
+void HAL_PWREx_EnableVddUSB(void)
+{
+ SET_BIT(PWR->CR2, PWR_CR2_USV);
+}
+
+/**
+ * @brief Disable VDDUSB supply.
+ * @retval None
+ */
+void HAL_PWREx_DisableVddUSB(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_CR2_USV);
+}
+#endif /* PWR_CR2_PVME1 */
+
+/****************************************************************************/
+
+/**
+ * @brief Enable Internal Wake-up Line.
+ * @retval None
+ */
+void HAL_PWREx_EnableInternalWakeUpLine(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_EIWUL);
+}
+
+/**
+ * @brief Disable Internal Wake-up Line.
+ * @retval None
+ */
+void HAL_PWREx_DisableInternalWakeUpLine(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_EIWUL);
+}
+
+#if defined(PWR_CR5_SMPSEN)
+/**
+ * @brief Enable BORH and SMPS step down converter forced in bypass mode
+ * interrupt for CPU1
+ * @retval None
+ */
+void HAL_PWREx_EnableBORH_SMPSBypassIT(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_EBORHSMPSFB);
+}
+
+/**
+ * @brief Disable BORH and SMPS step down converter forced in bypass mode
+ * interrupt for CPU1
+ * @retval None
+ */
+void HAL_PWREx_DisableBORH_SMPSBypassIT(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_EBORHSMPSFB);
+}
+#endif /* PWR_CR5_SMPSEN */
+
+/**
+ * @brief Enable RF Phase interrupt.
+ * @retval None
+ */
+void HAL_PWREx_EnableRFPhaseIT(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_ECRPE_Msk);
+}
+
+/**
+ * @brief Disable RF Phase interrupt.
+ * @retval None
+ */
+void HAL_PWREx_DisableRFPhaseIT(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_ECRPE_Msk);
+}
+
+
+/**
+ * @brief Enable BLE Activity interrupt.
+ * @retval None
+ */
+void HAL_PWREx_EnableBLEActivityIT(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_EBLEA);
+}
+
+/**
+ * @brief Disable BLE Activity interrupt.
+ * @retval None
+ */
+void HAL_PWREx_DisableBLEActivityIT(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_EBLEA);
+}
+
+#if defined(PWR_CR3_E802A)
+/**
+ * @brief Enable 802.15.4 Activity interrupt.
+ * @retval None
+ */
+void HAL_PWREx_Enable802ActivityIT(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_E802A);
+}
+
+/**
+ * @brief Disable 802.15.4 Activity interrupt.
+ * @retval None
+ */
+void HAL_PWREx_Disable802ActivityIT(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_E802A);
+}
+#endif /* PWR_CR3_E802A */
+
+/**
+ * @brief Enable CPU2 on-Hold interrupt.
+ * @retval None
+ */
+void HAL_PWREx_EnableHOLDC2IT(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_EC2H);
+}
+
+/**
+ * @brief Disable CPU2 on-Hold interrupt.
+ * @retval None
+ */
+void HAL_PWREx_DisableHOLDC2IT(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_EC2H);
+}
+
+/****************************************************************************/
+
+/**
+ * @brief Enable GPIO pull-up state in Standby and Shutdown modes.
+ * @note Set the relevant PUy bits of PWR_PUCRx register to configure the I/O in
+ * pull-up state in Standby and Shutdown modes.
+ * @note This state is effective in Standby and Shutdown modes only if APC bit
+ * is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
+ * @note The configuration is lost when exiting the Shutdown mode due to the
+ * power-on reset, maintained when exiting the Standby mode.
+ * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding
+ * PDy bit of PWR_PDCRx register is cleared unless it is reserved.
+ * @note Even if a PUy bit to set is reserved, the other PUy bits entered as input
+ * parameter at the same time are set.
+ * @param GPIO Specify the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to set
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ SET_BIT(PWR->PUCRA, GPIONumber);
+ CLEAR_BIT(PWR->PDCRA, GPIONumber);
+ break;
+ case PWR_GPIO_B:
+ SET_BIT(PWR->PUCRB, GPIONumber);
+ CLEAR_BIT(PWR->PDCRB, GPIONumber);
+ break;
+ case PWR_GPIO_C:
+ SET_BIT(PWR->PUCRC, GPIONumber);
+ CLEAR_BIT(PWR->PDCRC, GPIONumber);
+ break;
+#if defined(GPIOD)
+ case PWR_GPIO_D:
+ SET_BIT(PWR->PUCRD, GPIONumber);
+ CLEAR_BIT(PWR->PDCRD, GPIONumber);
+ break;
+#endif /* GPIOD */
+ case PWR_GPIO_E:
+ SET_BIT(PWR->PUCRE, (GPIONumber & PWR_PORTE_AVAILABLE_PINS));
+ CLEAR_BIT(PWR->PDCRE, (GPIONumber & PWR_PORTE_AVAILABLE_PINS));
+ break;
+ case PWR_GPIO_H:
+ SET_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable GPIO pull-up state in Standby mode and Shutdown modes.
+ * @note Reset the relevant PUy bits of PWR_PUCRx register used to configure the I/O
+ * in pull-up state in Standby and Shutdown modes.
+ * @note Even if a PUy bit to reset is reserved, the other PUy bits entered as input
+ * parameter at the same time are reset.
+ * @param GPIO Specifies the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to reset
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ CLEAR_BIT(PWR->PUCRA, GPIONumber);
+ break;
+ case PWR_GPIO_B:
+ CLEAR_BIT(PWR->PUCRB, GPIONumber);
+ break;
+ case PWR_GPIO_C:
+ CLEAR_BIT(PWR->PUCRC, GPIONumber);
+ break;
+#if defined(GPIOD)
+ case PWR_GPIO_D:
+ CLEAR_BIT(PWR->PUCRD, GPIONumber);
+ break;
+#endif /* GPIOD */
+ case PWR_GPIO_E:
+ CLEAR_BIT(PWR->PUCRE, (GPIONumber & PWR_PORTE_AVAILABLE_PINS));
+ break;
+ case PWR_GPIO_H:
+ CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+
+
+/**
+ * @brief Enable GPIO pull-down state in Standby and Shutdown modes.
+ * @note Set the relevant PDy bits of PWR_PDCRx register to configure the I/O in
+ * pull-down state in Standby and Shutdown modes.
+ * @note This state is effective in Standby and Shutdown modes only if APC bit
+ * is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
+ * @note The configuration is lost when exiting the Shutdown mode due to the
+ * power-on reset, maintained when exiting the Standby mode.
+ * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding
+ * PUy bit of PWR_PUCRx register is cleared unless it is reserved.
+ * @note Even if a PDy bit to set is reserved, the other PDy bits entered as input
+ * parameter at the same time are set.
+ * @param GPIO Specify the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to set
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ SET_BIT(PWR->PDCRA, GPIONumber);
+ CLEAR_BIT(PWR->PUCRA, GPIONumber);
+ break;
+ case PWR_GPIO_B:
+ SET_BIT(PWR->PDCRB, GPIONumber);
+ CLEAR_BIT(PWR->PUCRB, GPIONumber);
+ break;
+ case PWR_GPIO_C:
+ SET_BIT(PWR->PDCRC, GPIONumber);
+ CLEAR_BIT(PWR->PUCRC, GPIONumber);
+ break;
+#if defined(GPIOD)
+ case PWR_GPIO_D:
+ SET_BIT(PWR->PDCRD, GPIONumber);
+ CLEAR_BIT(PWR->PUCRD, GPIONumber);
+ break;
+#endif /* GPIOD */
+ case PWR_GPIO_E:
+ SET_BIT(PWR->PDCRE, (GPIONumber & PWR_PORTE_AVAILABLE_PINS));
+ CLEAR_BIT(PWR->PUCRE, (GPIONumber & PWR_PORTE_AVAILABLE_PINS));
+ break;
+ case PWR_GPIO_H:
+ SET_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable GPIO pull-down state in Standby and Shutdown modes.
+ * @note Reset the relevant PDy bits of PWR_PDCRx register used to configure the I/O
+ * in pull-down state in Standby and Shutdown modes.
+ * @note Even if a PDy bit to reset is reserved, the other PDy bits entered as input
+ * parameter at the same time are reset.
+ * @param GPIO Specifies the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to reset
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ CLEAR_BIT(PWR->PDCRA, GPIONumber);
+ break;
+ case PWR_GPIO_B:
+ CLEAR_BIT(PWR->PDCRB, GPIONumber);
+ break;
+ case PWR_GPIO_C:
+ CLEAR_BIT(PWR->PDCRC, GPIONumber);
+ break;
+#if defined(GPIOD)
+ case PWR_GPIO_D:
+ CLEAR_BIT(PWR->PDCRD, GPIONumber);
+ break;
+#endif /* GPIOD */
+ case PWR_GPIO_E:
+ CLEAR_BIT(PWR->PDCRE, (GPIONumber & PWR_PORTE_AVAILABLE_PINS));
+ break;
+ case PWR_GPIO_H:
+ CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Enable pull-up and pull-down configuration.
+ * @note When APC bit is set, the I/O pull-up and pull-down configurations defined in
+ * PWR_PUCRx and PWR_PDCRx registers are applied in Standby and Shutdown modes.
+ * @note Pull-up set by PUy bit of PWR_PUCRx register is not activated if the corresponding
+ * PDy bit of PWR_PDCRx register is also set (pull-down configuration priority is higher).
+ * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() API's ensure there
+ * is no conflict when setting PUy or PDy bit.
+ * @retval None
+ */
+void HAL_PWREx_EnablePullUpPullDownConfig(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_APC);
+}
+
+/**
+ * @brief Disable pull-up and pull-down configuration.
+ * @note When APC bit is cleared, the I/O pull-up and pull-down configurations defined in
+ * PWR_PUCRx and PWR_PDCRx registers are not applied in Standby and Shutdown modes.
+ * @retval None
+ */
+void HAL_PWREx_DisablePullUpPullDownConfig(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_APC);
+}
+
+/****************************************************************************/
+
+#if defined(PWR_CR5_SMPSEN)
+/**
+ * @brief Set BOR configuration
+ * @param BORConfiguration This parameter can be one of the following values:
+ * @arg @ref PWR_BOR_SYSTEM_RESET
+ * @arg @ref PWR_BOR_SMPS_FORCE_BYPASS
+ */
+void HAL_PWREx_SetBORConfig(uint32_t BORConfiguration)
+{
+ LL_PWR_SetBORConfig(BORConfiguration);
+}
+
+/**
+ * @brief Get BOR configuration
+ * @retval Returned value can be one of the following values:
+ * @arg @ref PWR_BOR_SYSTEM_RESET
+ * @arg @ref PWR_BOR_SMPS_FORCE_BYPASS
+ */
+uint32_t HAL_PWREx_GetBORConfig(void)
+{
+ return LL_PWR_GetBORConfig();
+}
+#endif /* PWR_CR5_SMPSEN */
+
+/****************************************************************************/
+/**
+ * @brief Hold the CPU and their allocated peripherals after reset or wakeup from stop or standby.
+ * @param CPU: Specifies the core to be held.
+ * This parameter can be one of the following values:
+ * @arg PWR_CORE_CPU2: Hold CPU2 and set CPU1 as master.
+ * @note Hold CPU2 with CPU1 as master by default.
+ * @retval None
+ */
+void HAL_PWREx_HoldCore(uint32_t CPU)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_CORE_HOLD_RELEASE(CPU));
+
+ LL_PWR_DisableBootC2();
+}
+
+/**
+ * @brief Release Cortex CPU2 and allocated peripherals after reset or wakeup from stop or standby.
+ * @param CPU: Specifies the core to be released.
+ * This parameter can be one of the following values:
+ * @arg PWR_CORE_CPU2: Release the CPU2 from holding.
+ * @retval None
+ */
+void HAL_PWREx_ReleaseCore(uint32_t CPU)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_CORE_HOLD_RELEASE(CPU));
+
+ LL_PWR_EnableBootC2();
+}
+
+/****************************************************************************/
+/**
+ * @brief Enable SRAM2a content retention in Standby mode.
+ * @note When RRS bit is set, SRAM2a is powered by the low-power regulator in
+ * Standby mode and its content is kept.
+ * @note On devices STM32WB15xx, STM32WB10xx, STM32WB1Mxx retention is extended
+ * to SRAM1, SRAM2a and SRAM2b.
+ * @retval None
+ */
+void HAL_PWREx_EnableSRAMRetention(void)
+{
+ LL_PWR_EnableSRAM2Retention();
+}
+
+/**
+ * @brief Disable SRAM2a content retention in Standby mode.
+ * @note When RRS bit is reset, SRAM2a is powered off in Standby mode
+ * and its content is lost.
+ * @note On devices STM32WB15xx, STM32WB10xx, STM32WB1Mxx retention is extended
+ * to SRAM1, SRAM2a and SRAM2b.
+ * @retval None
+ */
+void HAL_PWREx_DisableSRAMRetention(void)
+{
+ LL_PWR_DisableSRAM2Retention();
+}
+
+/****************************************************************************/
+/**
+ * @brief Enable Flash Power Down.
+ * @note This API allows to enable flash power down capabilities in low power
+ * run and low power sleep modes.
+ * @param PowerMode this can be a combination of following values:
+ * @arg @ref PWR_FLASHPD_LPRUN
+ * @arg @ref PWR_FLASHPD_LPSLEEP
+ * @retval None
+ */
+void HAL_PWREx_EnableFlashPowerDown(uint32_t PowerMode)
+{
+ assert_param(IS_PWR_FLASH_POWERDOWN(PowerMode));
+
+ if ((PowerMode & PWR_FLASHPD_LPRUN) != 0U)
+ {
+ /* Unlock bit FPDR */
+ WRITE_REG(PWR->CR1, 0x0000C1B0UL);
+ }
+
+ /* Set flash power down mode */
+ SET_BIT(PWR->CR1, PowerMode);
+}
+
+/**
+ * @brief Disable Flash Power Down.
+ * @note This API allows to disable flash power down capabilities in low power
+ * run and low power sleep modes.
+ * @param PowerMode this can be a combination of following values:
+ * @arg @ref PWR_FLASHPD_LPRUN
+ * @arg @ref PWR_FLASHPD_LPSLEEP
+ * @retval None
+ */
+void HAL_PWREx_DisableFlashPowerDown(uint32_t PowerMode)
+{
+ assert_param(IS_PWR_FLASH_POWERDOWN(PowerMode));
+
+ /* Set flash power down mode */
+ CLEAR_BIT(PWR->CR1, PowerMode);
+}
+
+/****************************************************************************/
+#if defined(PWR_CR2_PVME1)
+/**
+ * @brief Enable the Power Voltage Monitoring 1: VDDUSB versus 1.2V.
+ * @retval None
+ */
+void HAL_PWREx_EnablePVM1(void)
+{
+ SET_BIT(PWR->CR2, PWR_PVM_1);
+}
+
+/**
+ * @brief Disable the Power Voltage Monitoring 1: VDDUSB versus 1.2V.
+ * @retval None
+ */
+void HAL_PWREx_DisablePVM1(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_PVM_1);
+}
+#endif /* PWR_CR2_PVME1 */
+
+/**
+ * @brief Enable the Power Voltage Monitoring 3: VDDA versus 1.62V.
+ * @retval None
+ */
+void HAL_PWREx_EnablePVM3(void)
+{
+ SET_BIT(PWR->CR2, PWR_PVM_3);
+}
+
+/**
+ * @brief Disable the Power Voltage Monitoring 3: VDDA versus 1.62V.
+ * @retval None
+ */
+void HAL_PWREx_DisablePVM3(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_PVM_3);
+}
+
+
+
+
+/**
+ * @brief Configure the Peripheral Voltage Monitoring (PVM).
+ * @param sConfigPVM pointer to a PWR_PVMTypeDef structure that contains the
+ * PVM configuration information.
+ * @note The API configures a single PVM according to the information contained
+ * in the input structure. To configure several PVMs, the API must be singly
+ * called for each PVM used.
+ * @note Refer to the electrical characteristics of your device datasheet for
+ * more details about the voltage thresholds corresponding to each
+ * detection level and to each monitored supply.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_PWR_PVM_TYPE(sConfigPVM->PVMType));
+ assert_param(IS_PWR_PVM_MODE(sConfigPVM->Mode));
+
+ /* Configure EXTI 31 and 33 interrupts if so required:
+ scan thru PVMType to detect which PVMx is set and
+ configure the corresponding EXTI line accordingly. */
+ switch (sConfigPVM->PVMType)
+ {
+#if defined(PWR_CR2_PVME1)
+ case PWR_PVM_1:
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+ __HAL_PWR_PVM1_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVM1_EXTI_DISABLE_IT();
+ __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if ((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if ((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_EVENT();
+ }
+
+ /* Configure the edge */
+ if ((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if ((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE();
+ }
+ break;
+#endif /* PWR_CR2_PVME1 */
+
+ case PWR_PVM_3:
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+ __HAL_PWR_PVM3_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVM3_EXTI_DISABLE_IT();
+ __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if ((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if ((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_EVENT();
+ }
+
+ /* Configure the edge */
+ if ((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if ((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE();
+ }
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+
+ }
+
+ return status;
+}
+
+#if defined(PWR_CR5_SMPSEN)
+/**
+ * @brief Configure the SMPS step down converter.
+ * @note SMPS output voltage is calibrated in production,
+ * calibration parameters are applied to the voltage level parameter
+ * to reach the requested voltage value.
+ * @param sConfigSMPS pointer to a PWR_SMPSTypeDef structure that contains the
+ * SMPS configuration information.
+ * @note To set and enable SMPS operating mode, refer to function
+ * "HAL_PWREx_SMPS_SetMode()".
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_ConfigSMPS(PWR_SMPSTypeDef *sConfigSMPS)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_PWR_SMPS_STARTUP_CURRENT(sConfigSMPS->StartupCurrent));
+ assert_param(IS_PWR_SMPS_OUTPUT_VOLTAGE(sConfigSMPS->OutputVoltage));
+
+ __IO const uint32_t OutputVoltageLevel_calibration = (((*SMPS_VOLTAGE_CAL_ADDR) & SMPS_VOLTAGE_CAL) >> SMPS_VOLTAGE_CAL_POS); /* SMPS output voltage level calibrated in production */
+ int32_t TrimmingSteps; /* Trimming steps between theoretical output voltage and calibrated output voltage */
+ int32_t OutputVoltageLevelTrimmed; /* SMPS output voltage level after calibration: trimming value added to required level */
+
+ if (OutputVoltageLevel_calibration == 0UL)
+ {
+ /* Device with SMPS output voltage not calibrated in production: Apply output voltage value directly */
+
+ /* Update register */
+ MODIFY_REG(PWR->CR5, PWR_CR5_SMPSVOS, (sConfigSMPS->StartupCurrent | sConfigSMPS->OutputVoltage));
+ }
+ else
+ {
+ /* Device with SMPS output voltage calibrated in production: Apply output voltage value after correction by calibration value */
+
+ TrimmingSteps = ((int32_t)OutputVoltageLevel_calibration - (int32_t)(LL_PWR_SMPS_OUTPUT_VOLTAGE_1V50 >> PWR_CR5_SMPSVOS_Pos));
+ OutputVoltageLevelTrimmed = ((int32_t)((uint32_t)(sConfigSMPS->OutputVoltage >> PWR_CR5_SMPSVOS_Pos)) + (int32_t)TrimmingSteps);
+
+ /* Clamp value to voltage trimming bitfield range */
+ if (OutputVoltageLevelTrimmed < 0)
+ {
+ OutputVoltageLevelTrimmed = 0;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if (OutputVoltageLevelTrimmed > (int32_t)PWR_CR5_SMPSVOS)
+ {
+ OutputVoltageLevelTrimmed = (int32_t)PWR_CR5_SMPSVOS;
+ status = HAL_ERROR;
+ }
+ }
+
+ /* Update register */
+ MODIFY_REG(PWR->CR5, (PWR_CR5_SMPSSC | PWR_CR5_SMPSVOS),
+ (sConfigSMPS->StartupCurrent | ((uint32_t) OutputVoltageLevelTrimmed)));
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set SMPS operating mode.
+ * @param OperatingMode This parameter can be one of the following values:
+ * @arg @ref PWR_SMPS_BYPASS
+ * @arg @ref PWR_SMPS_STEP_DOWN (1)
+ *
+ * (1) SMPS operating mode step down or open depends on system low-power mode:
+ * - step down mode if system low power mode is run, LP run or stop,
+ * - open mode if system low power mode is Stop1, Stop2, Standby or Shutdown
+ * @retval None
+ */
+void HAL_PWREx_SMPS_SetMode(uint32_t OperatingMode)
+{
+ MODIFY_REG(PWR->CR5, PWR_CR5_SMPSEN, (OperatingMode & PWR_SR2_SMPSF) << (PWR_CR5_SMPSEN_Pos - PWR_SR2_SMPSF_Pos));
+}
+
+/**
+ * @brief Get SMPS effective operating mode
+ * @note SMPS operating mode can be changed by hardware, therefore
+ * requested operating mode can differ from effective low power mode.
+ * - dependency on system low-power mode:
+ * - step down mode if system low power mode is run, LP run or stop,
+ * - open mode if system low power mode is Stop1, Stop2, Standby or Shutdown
+ * - dependency on BOR level:
+ * - bypass mode if supply voltage drops below BOR level
+ * @note This functions check flags of SMPS operating modes step down
+ * and bypass. If the SMPS is not among these 2 operating modes,
+ * then it can be in mode off or open.
+ * @retval Returned value can be one of the following values:
+ * @arg @ref PWR_SMPS_BYPASS
+ * @arg @ref PWR_SMPS_STEP_DOWN (1)
+ *
+ * (1) SMPS operating mode step down or open depends on system low-power mode:
+ * - step down mode if system low power mode is run, LP run or stop,
+ * - open mode if system low power mode is Stop1, Stop2, Standby or Shutdown
+ */
+uint32_t HAL_PWREx_SMPS_GetEffectiveMode(void)
+{
+ return (uint32_t)(READ_BIT(PWR->SR2, (PWR_SR2_SMPSF | PWR_SR2_SMPSBF)));
+}
+#endif /* PWR_CR5_SMPSEN */
+
+/****************************************************************************/
+
+/**
+ * @brief Enable the WakeUp PINx functionality.
+ * @param WakeUpPinPolarity Specifies which Wake-Up pin to enable.
+ * This parameter can be one of the following legacy values which set the default polarity
+ * i.e. detection on high level (rising edge):
+ * @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5
+ *
+ * or one of the following value where the user can explicitly specify the enabled pin and
+ * the chosen polarity:
+ * @arg @ref PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW
+ * @arg @ref PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW
+ * @arg @ref PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW
+ * @arg @ref PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW
+ * @arg @ref PWR_WAKEUP_PIN5_HIGH or PWR_WAKEUP_PIN5_LOW
+ * @param wakeupTarget Specifies the wake-up target
+ * @arg @ref PWR_CORE_CPU1
+ * @arg @ref PWR_CORE_CPU2
+ * @note PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent.
+ * @retval None
+ */
+void HAL_PWREx_EnableWakeUpPin(uint32_t WakeUpPinPolarity, uint32_t wakeupTarget)
+{
+ assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinPolarity));
+
+ /* Specifies the Wake-Up pin polarity for the event detection
+ (rising or falling edge) */
+ MODIFY_REG(PWR->CR4, (PWR_C2CR3_EWUP & WakeUpPinPolarity), (WakeUpPinPolarity >> PWR_WUP_POLARITY_SHIFT));
+
+ /* Enable wake-up pin */
+ if (PWR_CORE_CPU2 == wakeupTarget)
+ {
+ SET_BIT(PWR->C2CR3, (PWR_C2CR3_EWUP & WakeUpPinPolarity));
+ }
+ else
+ {
+ SET_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinPolarity));
+ }
+}
+
+/**
+ * @brief Get the Wake-Up pin flag.
+ * @param WakeUpFlag specifies the Wake-Up PIN flag to check.
+ * This parameter can be one of the following values:
+ * @arg PWR_FLAG_WUF1: A wakeup event was received from PA0.
+ * @arg PWR_FLAG_WUF2: A wakeup event was received from PC13.
+ * @arg PWR_FLAG_WUF3: A wakeup event was received from PC12.
+ * @arg PWR_FLAG_WUF4: A wakeup event was received from PA2.
+ * @arg PWR_FLAG_WUF5: A wakeup event was received from PC5.
+ * @retval The Wake-Up pin flag.
+ */
+uint32_t HAL_PWREx_GetWakeupFlag(uint32_t WakeUpFlag)
+{
+ return (PWR->SR1 & (1UL << ((WakeUpFlag) & 31U)));
+}
+
+/**
+ * @brief Clear the Wake-Up pin flag.
+ * @param WakeUpFlag specifies the Wake-Up PIN flag to clear.
+ * This parameter can be one of the following values:
+ * @arg PWR_FLAG_WUF1: A wakeup event was received from PA0.
+ * @arg PWR_FLAG_WUF2: A wakeup event was received from PC13.
+ * @arg PWR_FLAG_WUF3: A wakeup event was received from PC12.
+ * @arg PWR_FLAG_WUF4: A wakeup event was received from PA2.
+ * @arg PWR_FLAG_WUF5: A wakeup event was received from PC5.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_ClearWakeupFlag(uint32_t WakeUpFlag)
+{
+ PWR->SCR = (1UL << ((WakeUpFlag) & 31U));
+
+ if ((PWR->SR1 & (1UL << ((WakeUpFlag) & 31U))) != 0U)
+ {
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/****************************************************************************/
+
+/**
+ * @brief Enter Low-power Run mode
+ * @note In Low-power Run mode, all I/O pins keep the same state as in Run mode.
+ * @note When Regulator is set to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the
+ * Flash in power-down mode in setting the RUN_PD bit in FLASH_ACR register.
+ * Additionally, the clock frequency must be reduced below 2 MHz.
+ * Setting RUN_PD in FLASH_ACR then appropriately reducing the clock frequency must
+ * be done before calling HAL_PWREx_EnableLowPowerRunMode() API.
+ * @retval None
+ */
+void HAL_PWREx_EnableLowPowerRunMode(void)
+{
+ /* Set Regulator parameter */
+ SET_BIT(PWR->CR1, PWR_CR1_LPR);
+}
+
+
+/**
+ * @brief Exit Low-power Run mode.
+ * @note Before HAL_PWREx_DisableLowPowerRunMode() completion, the function checks that
+ * REGLPF has been properly reset (otherwise, HAL_PWREx_DisableLowPowerRunMode
+ * returns HAL_TIMEOUT status). The system clock frequency can then be
+ * increased above 2 MHz.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void)
+{
+ uint32_t wait_loop_index;
+
+ /* Clear LPR bit */
+ CLEAR_BIT(PWR->CR1, PWR_CR1_LPR);
+
+ /* Wait until REGLPF is reset */
+ wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000U));
+ while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)) && (wait_loop_index != 0U))
+ {
+ wait_loop_index--;
+ }
+ if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))
+ {
+ return HAL_TIMEOUT;
+ }
+
+ return HAL_OK;
+}
+
+/****************************************************************************/
+
+/**
+ * @brief Enter Stop 0 mode.
+ * @note In Stop 0 mode, main and low voltage regulators are ON.
+ * @note In Stop 0 mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
+ * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
+ * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
+ * only to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * @note When exiting Stop 0 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @note By keeping the internal regulator ON during Stop 0 mode, the consumption
+ * is higher although the startup time is reduced.
+ * @note Case of Stop0 mode with SMPS: Before entering Stop 0 mode with SMPS Step Down converter enabled,
+ * the HSI16 must be kept on by enabling HSI kernel clock (set HSIKERON register bit).
+ * @note According to system power policy, system entering in Stop mode
+ * is depending on other CPU power mode.
+ * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Stop 0 mode with Main Regulator */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_STOP0);
+
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select Stop mode entry --------------------------------------------------*/
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+/**
+ * @brief Enter Stop 1 mode.
+ * @note In Stop 1 mode, only low power voltage regulator is ON.
+ * @note In Stop 1 mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
+ * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
+ * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
+ * only to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * @note When exiting Stop 1 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @note Due to low power mode, an additional startup delay is incurred when waking up from Stop 1 mode.
+ * @note According to system power policy, system entering in Stop mode
+ * is depending on other CPU power mode.
+ * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Stop 1 mode with Low-Power Regulator */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_STOP1);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select Stop mode entry --------------------------------------------------*/
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+#if defined(PWR_SUPPORT_STOP2)
+/**
+ * @brief Enter Stop 2 mode.
+ * @note In Stop 2 mode, only low power voltage regulator is ON.
+ * @note In Stop 2 mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped, the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with wakeup capability
+ * (LCD, LPTIM1, I2C3 and LPUART) can switch on the HSI to receive a frame, and switch off the HSI after
+ * receiving the frame if it is not a wakeup frame. In this case the HSI clock is propagated only
+ * to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * The voltage regulator is set in low-power mode but LPR bit must be cleared to enter stop 2 mode.
+ * Otherwise, Stop 1 mode is entered.
+ * @note When exiting Stop 2 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @note Case of Stop2 mode and debugger probe attached: a workaround should be applied.
+ * Issue specified in "ES0394 - STM32WB55Cx/Rx/Vx device errata":
+ * 2.2.9 Incomplete Stop 2 mode entry after a wakeup from debug upon EXTI line 48 event
+ * "With the JTAG debugger enabled on GPIO pins and after a wakeup from debug triggered by an event on EXTI
+ * line 48 (CDBGPWRUPREQ), the device may enter in a state in which attempts to enter Stop 2 mode are not fully
+ * effective ..."
+ * Workaround implementation example using LL driver:
+ * LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
+ * LL_C2_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
+ * @note According to system power policy, system entering in Stop mode
+ * is depending on other CPU power mode.
+ * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry)
+{
+ /* Check the parameter */
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Set Stop mode 2 */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_STOP2);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select Stop mode entry --------------------------------------------------*/
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+#endif /* PWR_SUPPORT_STOP2 */
+
+/**
+ * @brief Enter Shutdown mode.
+ * @note In Shutdown mode, the PLL, the HSI, the MSI, the LSI and the HSE oscillators are switched
+ * off. The voltage regulator is disabled and Vcore domain is powered off.
+ * SRAM1, SRAM2, BKRAM and registers contents are lost except for registers in the Backup domain.
+ * The BOR is not available.
+ * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state.
+ * @note According to system power policy, system entering in Shutdown mode
+ * is depending on other CPU power mode.
+ * @retval None
+ */
+void HAL_PWREx_EnterSHUTDOWNMode(void)
+{
+ /* Set Shutdown mode */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_SHUTDOWN);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* This option is used to ensure that store operations are completed */
+#if defined (__CC_ARM)
+ __force_stores();
+#endif /* __CC_ARM */
+
+ /* Request Wait For Interrupt */
+ __WFI();
+
+ /* Following code is executed after wake up if system didn't go to SHUTDOWN
+ * or STANDBY mode according to power policy */
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+
+/**
+ * @brief This function handles the PWR PVD/PVMx interrupt request.
+ * @note This API should be called under the PVD_PVM_IRQHandler().
+ * @retval None
+ */
+void HAL_PWREx_PVD_PVM_IRQHandler(void)
+{
+ /* Check PWR exti flag */
+ if (__HAL_PWR_PVD_EXTI_GET_FLAG() != 0U)
+ {
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback();
+
+ /* Clear PVD exti pending bit */
+ __HAL_PWR_PVD_EXTI_CLEAR_FLAG();
+ }
+
+#if defined(PWR_CR2_PVME1)
+ /* Next, successively check PVMx exti flags */
+ if (__HAL_PWR_PVM1_EXTI_GET_FLAG() != 0U)
+ {
+ /* PWR PVM1 interrupt user callback */
+ HAL_PWREx_PVM1Callback();
+
+ /* Clear PVM1 exti pending bit */
+ __HAL_PWR_PVM1_EXTI_CLEAR_FLAG();
+ }
+#endif /* PWR_CR2_PVME1 */
+
+ if (__HAL_PWR_PVM3_EXTI_GET_FLAG() != 0U)
+ {
+ /* PWR PVM3 interrupt user callback */
+ HAL_PWREx_PVM3Callback();
+
+ /* Clear PVM3 exti pending bit */
+ __HAL_PWR_PVM3_EXTI_CLEAR_FLAG();
+ }
+}
+
+#if defined(PWR_CR2_PVME1)
+/**
+ * @brief PWR PVM1 interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWREx_PVM1Callback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_PWREx_PVM1Callback() API can be implemented in the user file
+ */
+}
+#endif /* PWR_CR2_PVME1 */
+
+/**
+ * @brief PWR PVM3 interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWREx_PVM3Callback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_PWREx_PVM3Callback() API can be implemented in the user file
+ */
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c
new file mode 100644
index 0000000..d2c2f5d
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c
@@ -0,0 +1,1824 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_rcc.c
+ * @author MCD Application Team
+ * @brief RCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Reset and Clock Control (RCC) peripheral:
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### RCC specific features #####
+ ==============================================================================
+ [..]
+ After reset the device is running from Multiple Speed Internal oscillator
+ (4 MHz) with Flash 0 wait state. Flash prefetch buffer, D-Cache
+ and I-Cache are disabled, and all peripherals are off except internal
+ SRAM, Flash and JTAG.
+
+ (+) There is no prescaler on High speed (AHBs) and Low speed (APBs) buses:
+ all peripherals mapped on these buses are running at MSI speed.
+ (+) The clock for all peripherals is switched off, except the SRAM and FLASH.
+ (+) All GPIOs are in analog mode, except the JTAG pins which
+ are assigned to be used for debug purpose.
+
+ [..]
+ Once the device started from reset, the user application has to:
+ (+) Configure the clock source to be used to drive the System clock
+ (if the application needs higher frequency/performance)
+ (+) Configure the System clock frequency and Flash settings
+ (+) Configure the AHB and APB buses prescalers
+ (+) Enable the clock for the peripheral(s) to be used
+ (+) Configure the clock source(s) for peripherals which clocks are not
+ derived from the System clock (SAI1, RTC, ADC, USB/RNG, USART1, LPUART1, LPTIMx, I2Cx, SMPS)
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RCC RCC
+ * @brief RCC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup RCC_Private_Constants RCC Private Constants
+ * @{
+ */
+#define HSE_TIMEOUT_VALUE HSE_STARTUP_TIMEOUT
+#define HSI_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#define MSI_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#define LSI1_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#define LSI2_TIMEOUT_VALUE (3U) /* to be adjusted with DS */
+#define HSI48_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#define PLL_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#if defined(SAI1)
+#define PLLSAI1_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#endif /* SAI1 */
+#define PRESCALER_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#define LATENCY_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#define CLOCKSWITCH_TIMEOUT_VALUE (5000U) /* 5 s */
+
+#define PLLSOURCE_NONE (0U)
+#define MEGA_HZ (1000000U) /* Division factor to convert Hz in Mhz */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup RCC_Private_Macros RCC Private Macros
+ * @{
+ */
+
+#define RCC_GET_MCO_GPIO_PIN(__RCC_MCOx__) ((__RCC_MCOx__) & GPIO_PIN_MASK)
+
+#define RCC_GET_MCO_GPIO_AF(__RCC_MCOx__) (((__RCC_MCOx__) & RCC_MCO_GPIOAF_MASK) >> RCC_MCO_GPIOAF_POS)
+
+#define RCC_GET_MCO_GPIO_INDEX(__RCC_MCOx__) (((__RCC_MCOx__) & RCC_MCO_GPIOPORT_MASK) >> RCC_MCO_GPIOPORT_POS)
+
+#define RCC_GET_MCO_GPIO_PORT(__RCC_MCOx__) (IOPORT_BASE + ((0x00000400UL) * RCC_GET_MCO_GPIO_INDEX((__RCC_MCOx__))))
+
+#define RCC_PLL_OSCSOURCE_CONFIG(__HAL_RCC_PLLSOURCE__) \
+ (MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (uint32_t)(__HAL_RCC_PLLSOURCE__)))
+
+#define __COUNTOF(_A_) (sizeof(_A_) / sizeof(*(_A_)))
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup RCC_Private_Variables RCC Private Variables
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup RCC_Private_Functions RCC Private Functions
+ * @{
+ */
+static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t MSI_Range);
+static HAL_StatusTypeDef RCC_SetFlashLatency(uint32_t Flash_ClkSrcFreq, uint32_t VCORE_Voltage);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup RCC_Exported_Functions RCC Exported Functions
+ * @{
+ */
+
+/** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+ @verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to configure the internal and external oscillators
+ (HSE, HSI, LSE, MSI, LSI1, LSI2, PLL, CSS and MCO) and the System buses clocks (SYSCLK, HCLK1, HCLK2, HCLK4, PCLK1
+ and PCLK2).
+
+ [..] Internal/external clock and PLL configuration
+ (+) HSI (high-speed internal): 16 MHz factory-trimmed RC used directly or through
+ the PLL as System clock source.
+
+ (+) MSI (Multiple Speed Internal): Its frequency is software trimmable from 100KHZ to 48MHZ.
+ It can be used to generate the clock for the USB FS (48 MHz).
+ The number of flash wait states is automatically adjusted when MSI range is updated with
+ HAL_RCC_OscConfig() and the MSI is used as System clock source.
+
+ (+) LSI1/LSI2 (low-speed internal): 32 KHz low consumption RC used as IWDG and/or RTC
+ clock source.
+
+ (+) HSE (high-speed external): 32 MHz crystal oscillator used directly or
+ through the PLL as System clock source. Can be used also optionally as RTC clock source.
+
+ (+) LSE (low-speed external): 32.768 KHz oscillator used optionally as RTC clock source
+ or the RF system Auto-wakeup from Stop and Standby modes.
+
+ (+) PLL (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
+ (++) The first output is used to generate the high speed system clock (up to 64MHz).
+ (++) The second output is used to generate the clock for the USB FS (48 MHz),
+ the random analog generator (<=48 MHz)
+ (++) The third output is used to generate an accurate clock to achieve
+ high-quality audio performance on SAI interface.
+
+ (+) PLLSAI1 (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
+ (++) The first output is used to generate SAR ADC clock.
+ (++) The second output is used to generate the clock for the USB FS (48 MHz),
+ the random analog generator (<=48 MHz).
+ (++) The Third output is used to generate an accurate clock to achieve
+ high-quality audio performance on SAI interface.
+
+
+ (+) CSS (Clock security system): once enabled, if a HSE clock failure occurs
+ (HSE used directly or through PLL as System clock source), the System clock
+ is automatically switched to MSI or the HSI oscillator (depending on the
+ STOPWUCK configuration) and an interrupt is generated if enabled.
+ The interrupt is linked to the CPU1 and CPU2 NMI (Non-Maskable Interrupt) exception vector.
+
+ (+) LSECSS: once enabled, if a LSE clock failure occurs, the LSE
+ clock is no longer supplied to the RTC but no hardware action is made to the registers. If the
+ MSI was in PLL-mode, this mode is disabled.
+ In Standby mode a wakeup is generated. In other modes an interrupt can be sent to wakeup
+ the software
+
+ (+) MCO (microcontroller clock output): used to output MSI, LSI1, LSI2, HSI, LSE, HSE (before and
+ after stabilization), SYSCLK, HSI48 or main PLL clock (through a configurable prescaler)
+ on PA8, PB6 & PA15 pins.
+
+ [..] System, AHB and APB buses clocks configuration
+ (+) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI,
+ HSE and main PLL.
+ The AHB clock (HCLK1) is derived from System clock through configurable
+ prescaler and used to clock the CPU, memory and peripherals mapped
+ on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived
+ from AHB clock through configurable prescalers and used to clock
+ the peripherals mapped on these buses. You can use
+ HAL_RCC_GetSysClockFreq() function to retrieve the frequencies of these clocks.
+ The AHB4 clock (HCLK4) is derived from System clock through configurable
+ prescaler and used to clock the FLASH
+
+ -@- All the peripheral clocks are derived from the System clock (SYSCLK) except:
+
+ (+@) SAI: the SAI clock can be derived either from a specific PLL (PLLSAI1) or (PLLSYS) or
+ from an external clock mapped on the SAI_CKIN pin.
+ You have to use HAL_RCCEx_PeriphCLKConfig() function to configure this clock.
+ (+@) RTC: the RTC clock can be derived either from the LSI, LSE or HSE clock
+ divided by 32.
+ You have to use __HAL_RCC_RTC_ENABLE() and HAL_RCCEx_PeriphCLKConfig() function
+ to configure this clock.
+ (+@) USB FS and RNG: USB FS requires a frequency equal to 48 MHz
+ to work correctly, while RNG peripherals requires a frequency
+ equal or lower than to 48 MHz. This clock is derived of the main PLL or PLLSAI1
+ through PLLQ divider. You have to enable the peripheral clock and use
+ HAL_RCCEx_PeriphCLKConfig() function to configure this clock.
+ (+@) IWDG clock which is always the LSI clock.
+
+
+ (+) The maximum frequency of the SYSCLK, HCLK1, HCLK4, PCLK1 and PCLK2 is 64 MHz.
+ The maximum frequency of the HCLK2 is 32 MHz.
+ The clock source frequency should be adapted depending on the device voltage range
+ as listed in the Reference Manual "Clock source frequency versus voltage scaling" chapter.
+
+ @endverbatim
+
+ Table 1. HCLK4 clock frequency.
+ +-------------------------------------------------------+
+ | Latency | HCLK4 clock frequency (MHz) |
+ | |-------------------------------------|
+ | | voltage range 1 | voltage range 2 |
+ | | 1.2 V | 1.0 V |
+ |-----------------|------------------|------------------|
+ |0WS(1 CPU cycles)| HCLK4 <= 18 | HCLK4 <= 6 |
+ |-----------------|------------------|------------------|
+ |1WS(2 CPU cycles)| HCLK4 <= 36 | HCLK4 <= 12 |
+ |-----------------|------------------|------------------|
+ |2WS(3 CPU cycles)| HCLK4 <= 54 | HCLK4 <= 16 |
+ |-----------------|------------------|------------------|
+ |3WS(4 CPU cycles)| HCLK4 <= 64 | HCLK4 <= n.a. |
+ |-----------------|------------------|------------------|
+
+ * @{
+ */
+
+/**
+ * @brief Reset the RCC clock configuration to the default reset state.
+ * @note The default reset state of the clock configuration is given below:
+ * - MSI ON and used as system clock source
+ * - HSE, HSI, PLL, PLLSAI1
+ * - HCLK1, HCLK2, HCLK4, PCLK1 and PCLK2 prescalers set to 1.
+ * - CSS, MCO OFF
+ * - All interrupts disabled
+ * @note This function doesn't modify the configuration of the
+ * - Peripheral clocks
+ * - LSI, LSE and RTC clocks
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCC_DeInit(void)
+{
+ uint32_t tickstart;
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* MSI PLL OFF */
+ LL_RCC_MSI_DisablePLLMode();
+
+ /* Set MSION bit */
+ LL_RCC_MSI_Enable();
+
+ /* Wait till MSI is ready */
+ while (LL_RCC_MSI_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set MSIRANGE default value */
+ LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
+
+ /* Set MSITRIM bits to the reset value*/
+ LL_RCC_MSI_SetCalibTrimming(0);
+
+ /* Set HSITRIM bits to the reset value*/
+ LL_RCC_HSI_SetCalibTrimming(0x40U);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Reset CFGR register (MSI is selected as system clock source) */
+ CLEAR_REG(RCC->CFGR);
+
+ /* Wait till MSI is ready */
+ while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Reset HSION, HSIKERON, HSIASFS, HSEON, PLLON, PLLSAI11ON, HSEPRE bits */
+#if defined(SAI1)
+ CLEAR_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSIKERON | RCC_CR_HSIASFS | RCC_CR_HSEON | RCC_CR_HSEPRE | RCC_CR_PLLON |
+ RCC_CR_PLLSAI1ON);
+#else
+ CLEAR_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSIKERON | RCC_CR_HSIASFS | RCC_CR_HSEON | RCC_CR_HSEPRE | RCC_CR_PLLON);
+#endif /* SAI1 */
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while (LL_RCC_PLL_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* once PLL is OFF, reset PLLCFGR register to default value */
+ WRITE_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLQ_0 | RCC_PLLCFGR_PLLP_1 | RCC_PLLCFGR_PLLN_0);
+
+#if defined(SAI1)
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ /* once PLLSAI1 is OFF, reset PLLSAI1CFGR register to default value */
+ WRITE_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLR_0 | RCC_PLLSAI1CFGR_PLLQ_0 |
+ RCC_PLLSAI1CFGR_PLLP_1 | RCC_PLLSAI1CFGR_PLLN_0);
+#endif /* SAI1 */
+
+ /* Disable all interrupts */
+ CLEAR_REG(RCC->CIER);
+
+ /* Clear all interrupt flags */
+ WRITE_REG(RCC->CICR, 0xFFFFFFFFU);
+
+ /* EXTCFGR reset*/
+ LL_RCC_WriteReg(EXTCFGR, 0x00030000U);
+
+ /* Update the SystemCoreClock global variable */
+ SystemCoreClock = MSI_VALUE;
+
+ /* Adapt Systick interrupt period */
+ if (HAL_InitTick(uwTickPrio) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Initialize the RCC Oscillators according to the specified parameters in the
+ * @ref RCC_OscInitTypeDef.
+ * @param RCC_OscInitStruct pointer to a @ref RCC_OscInitTypeDef structure that
+ * contains the configuration information for the RCC Oscillators.
+ * @note The PLL is not disabled when used as system clock.
+ * @note The PLL source is not updated when used as PLLSAI1 clock source.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
+{
+ uint32_t tickstart;
+
+ /* Check Null pointer */
+ if (RCC_OscInitStruct == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
+
+ /*----------------------------- MSI Configuration --------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState));
+ assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue));
+ assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange));
+
+ /* When the MSI is used as system clock it will not be disabled */
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_plloscsrc = __HAL_RCC_GET_PLL_OSCSOURCE();
+ if ((temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_MSI) ||
+ ((temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (temp_plloscsrc == RCC_PLLSOURCE_MSI)))
+ {
+ if (RCC_OscInitStruct->MSIState == RCC_MSI_OFF)
+ {
+ return HAL_ERROR;
+ }
+ /* Otherwise, just the calibration and MSI range change are allowed */
+ else
+ {
+ /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
+ must be correctly programmed according to the frequency of the AHB4 clock
+ and the supply voltage of the device. */
+ if (RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE())
+ {
+ /* First increase number of wait states update if necessary */
+ if (RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Selects the Multiple Speed oscillator (MSI) clock range .*/
+ __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
+ /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
+ __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
+ }
+ else
+ {
+ /* Else, keep current flash latency while decreasing applies */
+ /* Selects the Multiple Speed oscillator (MSI) clock range .*/
+ __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
+ /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
+ __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
+
+ /* Decrease number of wait states update if necessary */
+ if (RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /* Update the SystemCoreClock global variable */
+ SystemCoreClock = HAL_RCC_GetHCLKFreq();
+
+ if (HAL_InitTick(uwTickPrio) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ /* Check the MSI State */
+ if (RCC_OscInitStruct->MSIState != RCC_MSI_OFF)
+ {
+ /* Enable the Internal High Speed oscillator (MSI). */
+ __HAL_RCC_MSI_ENABLE();
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait till MSI is ready */
+ while (LL_RCC_MSI_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Selects the Multiple Speed oscillator (MSI) clock range .*/
+ __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
+ /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
+ __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
+
+ }
+ else
+ {
+ /* Disable the Internal High Speed oscillator (MSI). */
+ __HAL_RCC_MSI_DISABLE();
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait till MSI is disabled */
+ while (LL_RCC_MSI_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+
+ /*------------------------------- HSE Configuration ------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
+
+ /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_plloscsrc = __HAL_RCC_GET_PLL_OSCSOURCE();
+ if ((temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_HSE) ||
+ ((temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (temp_plloscsrc == RCC_PLLSOURCE_HSE)))
+ {
+ if (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)
+ {
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Set the new HSE configuration ---------------------------------------*/
+ __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
+
+ /* Check the HSE State */
+ if (RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is ready */
+ while (LL_RCC_HSE_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is disabled */
+ while (LL_RCC_HSE_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+
+ /*----------------------------- HSI Configuration --------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
+ assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
+
+ /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_plloscsrc = __HAL_RCC_GET_PLL_OSCSOURCE();
+ if ((temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_HSI) ||
+ ((temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (temp_plloscsrc == RCC_PLLSOURCE_HSI)))
+ {
+ /* When HSI is used as system clock it will not be disabled */
+ if (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)
+ {
+ return HAL_ERROR;
+ }
+ /* Otherwise, just the calibration is allowed */
+ else
+ {
+ /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
+ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
+ }
+ }
+ else
+ {
+ /* Check the HSI State */
+ if (RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
+ {
+ /* Enable the Internal High Speed oscillator (HSI). */
+ __HAL_RCC_HSI_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI is ready */
+ while (LL_RCC_HSI_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
+ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
+ }
+ else
+ {
+ /* Disable the Internal High Speed oscillator (HSI). */
+ __HAL_RCC_HSI_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI is disabled */
+ while (LL_RCC_HSI_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ /*------------------------------ LSI Configuration (LSI1 or LSI2) -------------------------*/
+
+ if ((((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI1) == RCC_OSCILLATORTYPE_LSI1) || \
+ (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI2) == RCC_OSCILLATORTYPE_LSI2))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
+
+ /* Check the LSI State */
+ if (RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
+ {
+ /*------------------------------ LSI2 selected by default (when Switch ON) -------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI2) == RCC_OSCILLATORTYPE_LSI2)
+ {
+ assert_param(IS_RCC_LSI2_CALIBRATION_VALUE(RCC_OscInitStruct->LSI2CalibrationValue));
+
+ /* 1. Check LSI1 state and enable if required */
+ if (LL_RCC_LSI1_IsReady() == 0U)
+ {
+ /* This is required to enable LSI1 before enabling LSI2 */
+ __HAL_RCC_LSI1_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI1 is ready */
+ while (LL_RCC_LSI1_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI1_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* 2. Enable the Internal Low Speed oscillator (LSI2) and set trimming value */
+ __HAL_RCC_LSI2_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI2 is ready */
+ while (LL_RCC_LSI2_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI2_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Adjusts the Internal Low Spee oscillator (LSI2) calibration value */
+ __HAL_RCC_LSI2_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->LSI2CalibrationValue);
+
+ /* 3. Disable LSI1 */
+
+ /* LSI1 was initially not enable, require to disable it */
+ __HAL_RCC_LSI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI1 is disabled */
+ while (LL_RCC_LSI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI1_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /*------------------------------ LSI1 selected (only if LSI2 OFF)-------------------------*/
+
+ /* 1. Enable the Internal Low Speed oscillator (LSI1). */
+ __HAL_RCC_LSI1_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI1 is ready */
+ while (LL_RCC_LSI1_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI1_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ /*2. Switch OFF LSI2*/
+
+ /* Disable the Internal Low Speed oscillator (LSI2). */
+ __HAL_RCC_LSI2_DISABLE();
+
+ /* Wait till LSI2 is disabled */
+ while (LL_RCC_LSI2_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI2_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+
+ /* Disable the Internal Low Speed oscillator (LSI2). */
+ __HAL_RCC_LSI2_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI2 is disabled */
+ while (LL_RCC_LSI2_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI2_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Disable the Internal Low Speed oscillator (LSI1). */
+ __HAL_RCC_LSI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI1 is disabled */
+ while (LL_RCC_LSI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI1_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /*------------------------------ LSE Configuration -------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
+
+ /* Update LSE configuration in Backup Domain control register */
+ /* Requires to enable write access to Backup Domain of necessary */
+
+ if (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
+ {
+ /* Enable write access to Backup domain */
+ HAL_PWR_EnableBkUpAccess();
+
+ /* Wait for Backup domain Write protection disable */
+ tickstart = HAL_GetTick();
+
+ while (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Set the new LSE configuration -----------------------------------------*/
+ __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
+
+ /* Check the LSE State */
+ if (RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while (LL_RCC_LSE_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is disabled */
+ while (LL_RCC_LSE_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ }
+#if defined(RCC_HSI48_SUPPORT)
+ /*------------------------------ HSI48 Configuration -----------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State));
+
+ /* Check the HSI State */
+ if (RCC_OscInitStruct->HSI48State != RCC_HSI48_OFF)
+ {
+ /* Enable the Internal Low Speed oscillator (HSI48). */
+ __HAL_RCC_HSI48_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI48 is ready */
+ while (LL_RCC_HSI48_IsReady() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Disable the Internal Low Speed oscillator (HSI48). */
+ __HAL_RCC_HSI48_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI48 is disabled */
+ while (LL_RCC_HSI48_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+#endif /* RCC_HSI48_SUPPORT */
+ /*-------------------------------- PLL Configuration -----------------------*/
+ /* Check the parameters */
+ assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
+
+ if (RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
+ {
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_pllconfig = RCC->PLLCFGR;
+
+ /* PLL On ? */
+ if (RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
+ assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
+ assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
+ assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
+ assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
+ assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));
+
+ /* Do nothing if PLL configuration is unchanged */
+ if ((READ_BIT(temp_pllconfig, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
+ (READ_BIT(temp_pllconfig, RCC_PLLCFGR_PLLM) != RCC_OscInitStruct->PLL.PLLM) ||
+ ((READ_BIT(temp_pllconfig, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos) != RCC_OscInitStruct->PLL.PLLN) ||
+ (READ_BIT(temp_pllconfig, RCC_PLLCFGR_PLLP) != RCC_OscInitStruct->PLL.PLLP) ||
+ (READ_BIT(temp_pllconfig, RCC_PLLCFGR_PLLQ) != RCC_OscInitStruct->PLL.PLLQ) ||
+ (READ_BIT(temp_pllconfig, RCC_PLLCFGR_PLLR) != RCC_OscInitStruct->PLL.PLLR))
+ {
+ /* Check if the PLL is used as system clock or not */
+ if (temp_sysclksrc != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
+ {
+#if defined(SAI1)
+ /* Check if main PLL can be updated */
+ /* Not possible if the source is shared by other enabled PLLSAIx */
+ if (READ_BIT(RCC->CR, RCC_CR_PLLSAI1ON) != 0U)
+
+ {
+ return HAL_ERROR;
+ }
+ else
+#endif /* SAI1 */
+ {
+ /* Disable the main PLL. */
+ __HAL_RCC_PLL_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure the main PLL clock source, multiplication and division factors. */
+ __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
+ RCC_OscInitStruct->PLL.PLLM,
+ RCC_OscInitStruct->PLL.PLLN,
+ RCC_OscInitStruct->PLL.PLLP,
+ RCC_OscInitStruct->PLL.PLLQ,
+ RCC_OscInitStruct->PLL.PLLR);
+
+ /* Enable the main PLL. */
+ __HAL_RCC_PLL_ENABLE();
+
+ /* Enable PLL System Clock output. */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* PLL is already used as System core clock */
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* PLL configuration is unchanged */
+ /* Re-enable PLL if it was disabled (ie. low power mode) */
+ if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
+ {
+ /* Enable the main PLL. */
+ __HAL_RCC_PLL_ENABLE();
+
+ /* Enable PLL System Clock output. */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Check that PLL is not used as system clock or not */
+ if (temp_sysclksrc != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
+ {
+ /* Disable the main PLL. */
+ __HAL_RCC_PLL_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is disabled */
+ while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Disable the PLL source and outputs to save power when PLL is off */
+#if defined(SAI1) && defined(USB)
+ CLEAR_BIT(RCC->PLLCFGR, (RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLPEN | RCC_PLLCFGR_PLLQEN | RCC_PLLCFGR_PLLREN));
+#else
+ CLEAR_BIT(RCC->PLLCFGR, (RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLREN));
+#endif /* SAI1 && USB */
+ }
+ else
+ {
+ /* PLL is already used as System core clock */
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initialize the CPU, AHB and APB buses clocks according to the specified
+ * parameters in the RCC_ClkInitStruct.
+ * @param RCC_ClkInitStruct pointer to a @ref RCC_ClkInitTypeDef structure that
+ * contains the configuration information for the RCC peripheral.
+ * @param FLatency FLASH Latency
+ * This parameter can be one of the following values:
+ * @arg FLASH_LATENCY_0 FLASH 0 Latency cycle
+ * @arg FLASH_LATENCY_1 FLASH 1 Latency cycle
+ * @arg FLASH_LATENCY_2 FLASH 2 Latency cycle
+ * @arg FLASH_LATENCY_3 FLASH 3 Latency cycle
+ *
+ * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency
+ * and updated by @ref HAL_RCC_GetHCLKFreq() function called within this function
+ *
+ * @note The MSI is used by default as system clock source after
+ * startup from Reset, wake-up from STANDBY mode. After restart from Reset,
+ * the MSI frequency is set to its default value 4 MHz.
+ *
+ * @note The HSI can be selected as system clock source after
+ * from STOP modes or in case of failure of the HSE used directly or indirectly
+ * as system clock (if the Clock Security System CSS is enabled).
+ *
+ * @note A switch from one clock source to another occurs only if the target
+ * clock source is ready (clock stable after startup delay or PLL locked).
+ * If a clock source which is not yet ready is selected, the switch will
+ * occur when the clock source is ready.
+ *
+ * @note You can use @ref HAL_RCC_GetClockConfig() function to know which clock is
+ * currently used as system clock source.
+ *
+ * @note Depending on the device voltage range, the software has to set correctly
+ * HPRE[3:0] bits to ensure that HCLK1 not exceed the maximum allowed frequency
+ * (for more details refer to section above "Initialization/de-initialization functions")
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
+{
+ uint32_t tickstart;
+
+ /* Check Null pointer */
+ if (RCC_ClkInitStruct == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
+ assert_param(IS_FLASH_LATENCY(FLatency));
+
+ /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
+ must be correctly programmed according to the frequency of the FLASH clock
+ (HCLK4) and the supply voltage of the device. */
+
+ /* Increasing the number of wait states because of higher CPU frequency */
+ if (FLatency > __HAL_FLASH_GET_LATENCY())
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLatency);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ while (__HAL_FLASH_GET_LATENCY() != FLatency)
+ {
+ if ((HAL_GetTick() - tickstart) > LATENCY_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*-------------------------- HCLK1 Configuration --------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
+ {
+ assert_param(IS_RCC_HCLKx(RCC_ClkInitStruct->AHBCLKDivider));
+ LL_RCC_SetAHBPrescaler(RCC_ClkInitStruct->AHBCLKDivider);
+
+ /* HCLK1 prescaler flag when value applied */
+ tickstart = HAL_GetTick();
+ while (LL_RCC_IsActiveFlag_HPRE() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PRESCALER_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*-------------------------- HCLK2 Configuration --------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK2) == RCC_CLOCKTYPE_HCLK2)
+ {
+ assert_param(IS_RCC_HCLKx(RCC_ClkInitStruct->AHBCLK2Divider));
+ LL_C2_RCC_SetAHBPrescaler(RCC_ClkInitStruct->AHBCLK2Divider);
+
+ /* HCLK2 prescaler flag when value applied */
+ tickstart = HAL_GetTick();
+ while (LL_RCC_IsActiveFlag_C2HPRE() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PRESCALER_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /*-------------------------- HCLK4 Configuration --------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK4) == RCC_CLOCKTYPE_HCLK4)
+ {
+ assert_param(IS_RCC_HCLKx(RCC_ClkInitStruct->AHBCLK4Divider));
+ LL_RCC_SetAHB4Prescaler(RCC_ClkInitStruct->AHBCLK4Divider);
+
+ /* AHB shared prescaler flag when value applied */
+ tickstart = HAL_GetTick();
+ while (LL_RCC_IsActiveFlag_SHDHPRE() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PRESCALER_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*-------------------------- PCLK1 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
+ {
+ assert_param(IS_RCC_PCLKx(RCC_ClkInitStruct->APB1CLKDivider));
+ LL_RCC_SetAPB1Prescaler(RCC_ClkInitStruct->APB1CLKDivider);
+
+ /* APB1 prescaler flag when value applied */
+ tickstart = HAL_GetTick();
+ while (LL_RCC_IsActiveFlag_PPRE1() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PRESCALER_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*-------------------------- PCLK2 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
+ {
+ assert_param(IS_RCC_PCLKx(RCC_ClkInitStruct->APB2CLKDivider));
+ LL_RCC_SetAPB2Prescaler((RCC_ClkInitStruct->APB2CLKDivider) << 3U);
+
+ /* APB2 prescaler flag when value applied */
+ tickstart = HAL_GetTick();
+ while (LL_RCC_IsActiveFlag_PPRE2() == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PRESCALER_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*------------------------- SYSCLK Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
+ {
+ assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
+
+ /* HSE is selected as System Clock Source */
+ if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
+ {
+ /* Check the HSE ready flag */
+ if (LL_RCC_HSE_IsReady() == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* PLL is selected as System Clock Source */
+ else if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
+ {
+ /* Check the PLL ready flag */
+ if (LL_RCC_PLL_IsReady() == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* MSI is selected as System Clock Source */
+ else if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
+ {
+ /* Check the MSI ready flag */
+ if (LL_RCC_MSI_IsReady() == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* HSI is selected as System Clock Source */
+ else
+ {
+ /* Check the HSI ready flag */
+ if (LL_RCC_HSI_IsReady() == 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ }
+
+ /* apply system clock switch */
+ LL_RCC_SetSysClkSource(RCC_ClkInitStruct->SYSCLKSource);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* check system clock source switch status */
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
+ {
+ if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Decreasing the number of wait states because of lower CPU frequency */
+ if (FLatency < __HAL_FLASH_GET_LATENCY())
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLatency);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ while (__HAL_FLASH_GET_LATENCY() != FLatency)
+ {
+ if ((HAL_GetTick() - tickstart) > LATENCY_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*---------------------------------------------------------------------------*/
+
+ /* Update the SystemCoreClock global variable */
+ SystemCoreClock = HAL_RCC_GetHCLKFreq();
+
+ /* Configure the source of time base considering new system clocks settings*/
+ return HAL_InitTick(HAL_GetTickPrio());
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions
+ * @brief RCC clocks control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to:
+
+ (+) Output clock to MCO pin.
+ (+) Retrieve current clock frequencies.
+ (+) Enable the Clock Security System.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Select the clock source to output on MCO1 pin(PA8) or MCO2 pin (PB6) or MCO3 pin (PA15).
+ * @note PA8, PB6 or PA15 should be configured in alternate function mode.
+ * @param RCC_MCOx specifies the output direction for the clock source.
+ * @arg @ref RCC_MCO1_PA8 Clock source to output on MCO1 pin(PA8)
+ * @arg @ref RCC_MCO2_PB6 Clock source to output on MCO2 pin(PB6)
+ * @arg @ref RCC_MCO3_PA15 Clock source to output on MCO3 pin(PA15)
+ * @param RCC_MCOSource specifies the clock source to output.
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_MCO1SOURCE_NOCLOCK MCO output disabled, no clock on MCO
+ * @arg @ref RCC_MCO1SOURCE_SYSCLK system clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_MSI MSI clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_HSI HSI clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_HSE HSE clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_PLLCLK main PLL clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_LSI1 LSI1 clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_LSI2 LSI2 clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_LSE LSE clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48
+ * @arg @ref RCC_MCO1SOURCE_HSE_BEFORE_STAB HSE clock before stabilization selected as MCO source
+ * @param RCC_MCODiv specifies the MCO prescaler.
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_MCODIV_1 no division applied to MCO clock
+ * @arg @ref RCC_MCODIV_2 division by 2 applied to MCO clock
+ * @arg @ref RCC_MCODIV_4 division by 4 applied to MCO clock
+ * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock
+ * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock
+ * @retval None
+ */
+void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
+{
+ GPIO_InitTypeDef gpio_initstruct;
+ uint32_t mcoindex;
+ uint32_t mco_gpio_index;
+ GPIO_TypeDef *mco_gpio_port;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_MCO(RCC_MCOx));
+
+ /* Common GPIO init parameters */
+ gpio_initstruct.Mode = GPIO_MODE_AF_PP;
+ gpio_initstruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ gpio_initstruct.Pull = GPIO_NOPULL;
+
+ /* Get MCOx selection */
+ mcoindex = RCC_MCOx & RCC_MCO_INDEX_MASK;
+
+ /* Get MCOx GPIO Port */
+ mco_gpio_port = (GPIO_TypeDef *) RCC_GET_MCO_GPIO_PORT(RCC_MCOx);
+
+ /* MCOx Clock Enable */
+ mco_gpio_index = RCC_GET_MCO_GPIO_INDEX(RCC_MCOx);
+ SET_BIT(RCC->AHB2ENR, (1UL << mco_gpio_index));
+
+ /* Configure the MCOx pin in alternate function mode */
+ gpio_initstruct.Pin = RCC_GET_MCO_GPIO_PIN(RCC_MCOx);
+ gpio_initstruct.Alternate = RCC_GET_MCO_GPIO_AF(RCC_MCOx);
+ HAL_GPIO_Init(mco_gpio_port, &gpio_initstruct);
+
+ if (mcoindex == RCC_MCO1_INDEX)
+ {
+ assert_param(IS_RCC_MCODIV(RCC_MCODiv));
+ assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
+ /* Mask MCOSEL[] and MCOPRE[] bits then set MCO clock source and prescaler */
+ LL_RCC_ConfigMCO(RCC_MCOSource, RCC_MCODiv);
+ }
+ else if (mcoindex == RCC_MCO2_INDEX)
+ {
+ assert_param(IS_RCC_MCODIV(RCC_MCODiv));
+ assert_param(IS_RCC_MCO2SOURCE(RCC_MCOSource));
+ /* Mask MCOSEL[] and MCOPRE[] bits then set MCO clock source and prescaler */
+ LL_RCC_ConfigMCO(RCC_MCOSource, RCC_MCODiv);
+ }
+#if defined(RCC_MCO3_SUPPORT)
+ else if (mcoindex == RCC_MCO3_INDEX)
+ {
+ assert_param(IS_RCC_MCODIV(RCC_MCODiv));
+ assert_param(IS_RCC_MCO3SOURCE(RCC_MCOSource));
+ /* Mask MCOSEL[] and MCOPRE[] bits then set MCO clock source and prescaler */
+ LL_RCC_ConfigMCO(RCC_MCOSource, RCC_MCODiv);
+ }
+#endif /* RCC_MCO3_SUPPORT */
+ else
+ {}
+}
+
+/**
+ * @brief Return the SYSCLK frequency.
+ *
+ * @note The system computed by this function is not the real
+ * frequency in the chip. It is calculated based on the predefined
+ * constant and the selected clock source:
+ * @note If SYSCLK source is MSI, function returns values based on MSI range
+ * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
+ * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
+ * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**),
+ * HSI_VALUE(*) or MSI Value multiplied/divided by the PLL factors.
+ * @note (*) HSI_VALUE is a constant defined in stm32wbxx_hal_conf.h file (default value
+ * 16 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note (**) HSE_VALUE is a constant defined in stm32wbxx_hal_conf.h file (default value
+ * 32 MHz), user has to ensure that HSE_VALUE is same as the real
+ * frequency of the crystal used. Otherwise, this function may
+ * have wrong result.
+ *
+ * @note The result of this function could be not correct when using fractional
+ * value for HSE crystal.
+ *
+ * @note This function can be used by the user application to compute the
+ * baudrate for the communication peripherals or configure other parameters.
+ *
+ * @note Each time SYSCLK changes, this function must be called to update the
+ * right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
+ *
+ *
+ * @retval SYSCLK frequency
+ */
+uint32_t HAL_RCC_GetSysClockFreq(void)
+{
+ uint32_t pllsource;
+ uint32_t sysclockfreq;
+ uint32_t pllinputfreq;
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+
+ if (temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_MSI)
+ {
+ /* Retrieve MSI frequency range in HZ*/
+ /* MSI used as system clock source */
+ sysclockfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ }
+ else if (temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_HSI)
+ {
+ /* HSI used as system clock source */
+ sysclockfreq = HSI_VALUE;
+ }
+ else if (temp_sysclksrc == RCC_SYSCLKSOURCE_STATUS_HSE)
+ {
+ /* HSE used as system clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ sysclockfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ sysclockfreq = HSE_VALUE;
+ }
+ }
+ else
+ {
+ /* PLL used as system clock source */
+ pllsource = LL_RCC_PLL_GetMainSource();
+ switch (pllsource)
+ {
+ case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+ case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+ case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ sysclockfreq = __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), LL_RCC_PLL_GetN(),
+ LL_RCC_PLL_GetR());
+ }
+
+ return sysclockfreq;
+}
+
+/**
+ * @brief Return the HCLK frequency.
+ * @retval HCLK frequency in Hz
+ */
+uint32_t HAL_RCC_GetHCLKFreq(void)
+{
+ /* Get SysClock and Compute HCLK1 frequency ---------------------------*/
+ return ((uint32_t)(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(), LL_RCC_GetAHBPrescaler())));
+}
+
+/**
+ * @brief Return the HCLK2 frequency.
+ * @retval HCLK2 frequency in Hz
+ */
+uint32_t HAL_RCC_GetHCLK2Freq(void)
+{
+ /* Get SysClock and Compute HCLK2 frequency ---------------------------*/
+ return ((uint32_t)(__LL_RCC_CALC_HCLK2_FREQ(HAL_RCC_GetSysClockFreq(), LL_C2_RCC_GetAHBPrescaler())));
+}
+
+/**
+ * @brief Return the HCLK4 frequency.
+ * @retval HCLK4 frequency in Hz
+ */
+uint32_t HAL_RCC_GetHCLK4Freq(void)
+{
+ /* Get SysClock and Compute AHB4 frequency ---------------------------*/
+ return ((uint32_t)(__LL_RCC_CALC_HCLK4_FREQ(HAL_RCC_GetSysClockFreq(), LL_RCC_GetAHB4Prescaler())));
+}
+
+/**
+ * @brief Return the PCLK1 frequency.
+ * @note Each time PCLK1 changes, this function must be called to update the
+ * right PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
+ * @retval PCLK1 frequency in Hz
+ */
+uint32_t HAL_RCC_GetPCLK1Freq(void)
+{
+ /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
+ return ((uint32_t)(__LL_RCC_CALC_PCLK1_FREQ(HAL_RCC_GetHCLKFreq(), LL_RCC_GetAPB1Prescaler())));
+}
+
+/**
+ * @brief Return the PCLK2 frequency.
+ * @note Each time PCLK2 changes, this function must be called to update the
+ * right PCLK2 value. Otherwise, any configuration based on this function will be incorrect.
+ * @retval PCLK2 frequency in Hz
+ */
+uint32_t HAL_RCC_GetPCLK2Freq(void)
+{
+ /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
+ return ((uint32_t)(__LL_RCC_CALC_PCLK2_FREQ(HAL_RCC_GetHCLKFreq(), LL_RCC_GetAPB2Prescaler())));
+}
+
+/**
+ * @brief Configure the RCC_OscInitStruct according to the internal
+ * RCC configuration registers.
+ * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
+ * will be configured.
+ * @retval None
+ */
+void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
+{
+ uint32_t regvalue;
+ uint32_t regICSRvalue;
+ uint32_t regPLLCFGRvalue;
+
+ /* Check the parameters */
+ assert_param(RCC_OscInitStruct != (void *)NULL);
+
+ /* Set all possible values for the Oscillator type parameter ---------------*/
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \
+ RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI1 | RCC_OSCILLATORTYPE_LSI2;
+
+#if defined(RCC_HSI48_SUPPORT)
+ RCC_OscInitStruct->OscillatorType |= RCC_OSCILLATORTYPE_HSI48;
+#endif /* RCC_HSI48_SUPPORT */
+
+ /* Get register values */
+ regvalue = RCC->CR; /* Control register */
+ regICSRvalue = RCC->ICSCR; /* Get Internal Clock Sources Calibration register */
+ regPLLCFGRvalue = RCC->PLLCFGR; /* Get PLL Configuration register */
+
+ /* Get the HSE configuration -----------------------------------------------*/
+ RCC_OscInitStruct->HSEState = (regvalue & RCC_CR_HSEON);
+
+ /* Get the MSI configuration -----------------------------------------------*/
+ RCC_OscInitStruct->MSIState = (regvalue & RCC_CR_MSION);
+ RCC_OscInitStruct->MSICalibrationValue = (regICSRvalue & RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos;
+ RCC_OscInitStruct->MSIClockRange = (regvalue & RCC_CR_MSIRANGE);
+
+ /* Get the HSI configuration -----------------------------------------------*/
+ RCC_OscInitStruct->HSIState = (regvalue & RCC_CR_HSION);
+ RCC_OscInitStruct->HSICalibrationValue = ((regICSRvalue & RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos);
+
+ /* Get the PLL configuration -----------------------------------------------*/
+ RCC_OscInitStruct->PLL.PLLState = ((regvalue & RCC_CR_PLLON) >> RCC_CR_PLLON_Pos) + 1U;
+ RCC_OscInitStruct->PLL.PLLSource = (regPLLCFGRvalue & RCC_PLLCFGR_PLLSRC);
+ RCC_OscInitStruct->PLL.PLLM = (regPLLCFGRvalue & RCC_PLLCFGR_PLLM);
+ RCC_OscInitStruct->PLL.PLLN = ((regPLLCFGRvalue & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
+ RCC_OscInitStruct->PLL.PLLP = (regPLLCFGRvalue & RCC_PLLCFGR_PLLP);
+ RCC_OscInitStruct->PLL.PLLQ = (regPLLCFGRvalue & RCC_PLLCFGR_PLLQ);
+ RCC_OscInitStruct->PLL.PLLR = (regPLLCFGRvalue & RCC_PLLCFGR_PLLR);
+
+ /* Get Backup Domain register */
+ regvalue = RCC->BDCR;
+
+ /* Get the LSE configuration -----------------------------------------------*/
+ RCC_OscInitStruct->LSEState = (regvalue & RCC_LSE_BYPASS);
+
+ /* Get Control/Status register */
+ regvalue = RCC->CSR;
+
+ /* Get the LSI configuration -----------------------------------------------*/
+ RCC_OscInitStruct->LSIState = ((regvalue & RCC_LSI_ON) > 0U) ? RCC_LSI_ON : 0U;
+
+#if defined(RCC_HSI48_SUPPORT)
+ /* Get Control/Status register */
+ regvalue = RCC->CRRCR;
+
+ /* Get the HSI48 configuration ---------------------------------------------*/
+ RCC_OscInitStruct->HSI48State = (regvalue & RCC_CRRCR_HSI48ON);
+#endif /* RCC_HSI48_SUPPORT */
+
+}
+
+/**
+ * @brief Configure the RCC_ClkInitStruct according to the internal
+ * RCC configuration registers.
+ * @param RCC_ClkInitStruct Pointer to a @ref RCC_ClkInitTypeDef structure that
+ * will be configured.
+ * @param pFLatency Pointer on the Flash Latency.
+ * @retval None
+ */
+void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency)
+{
+ /* Check the parameters */
+ assert_param(RCC_ClkInitStruct != (void *)NULL);
+ assert_param(pFLatency != (void *)NULL);
+
+ /* Set all possible values for the Clock type parameter --------------------*/
+ RCC_ClkInitStruct->ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 |
+ RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_HCLK2 | RCC_CLOCKTYPE_HCLK4);
+
+ /* Get the SYSCLK configuration --------------------------------------------*/
+ RCC_ClkInitStruct->SYSCLKSource = LL_RCC_GetSysClkSource();
+
+ /* Get the HCLK configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->AHBCLKDivider = LL_RCC_GetAHBPrescaler();
+
+ /* Get the APB1 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB1CLKDivider = LL_RCC_GetAPB1Prescaler();
+
+ /* Get the APB2 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB2CLKDivider = LL_RCC_GetAPB2Prescaler();
+
+ /* Get the AHBCLK2Divider configuration ------------------------------------*/
+ RCC_ClkInitStruct->AHBCLK2Divider = LL_C2_RCC_GetAHBPrescaler();
+
+ /* Get the AHBCLK4Divider configuration ------------------------------------*/
+ RCC_ClkInitStruct->AHBCLK4Divider = LL_RCC_GetAHB4Prescaler();
+
+ /* Get the Flash Wait State (Latency) configuration ------------------------*/
+ *pFLatency = __HAL_FLASH_GET_LATENCY();
+}
+
+/**
+ * @brief Enable the Clock Security System.
+ * @note If a failure is detected on the HSE oscillator clock, this oscillator
+ * is automatically disabled and an interrupt is generated to inform the
+ * software about the failure (Clock Security System Interrupt, CSSI),
+ * allowing the MCU to perform rescue operations. The CSSI is linked to
+ * CPU1 and CPU2 NMI (Non-Maskable Interrupt) exception vector.
+ * @note The Clock Security System can only be cleared by reset.
+ * @retval None
+ */
+void HAL_RCC_EnableCSS(void)
+{
+ LL_RCC_HSE_EnableCSS();
+}
+
+/**
+ * @brief Handle the RCC HSE Clock Security System interrupt request.
+ * @note This API should be called under the NMI_Handler().
+ * @retval None
+ */
+void HAL_RCC_NMI_IRQHandler(void)
+{
+ /* Check RCC CSSF interrupt flag */
+ if (__HAL_RCC_GET_IT(RCC_IT_HSECSS))
+ {
+ /* RCC Clock Security System interrupt user callback */
+ HAL_RCC_CSSCallback();
+
+ /* Clear RCC CSS pending bit */
+ __HAL_RCC_CLEAR_IT(RCC_IT_HSECSS);
+ }
+}
+
+/**
+ * @brief Handle the RCC HSE Clock Security System interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCC_CSSCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCC_CSSCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Get and clear reset flags
+ * @param None
+ * @note Once reset flags are retrieved, this API is clearing them in order
+ * to isolate next reset reason.
+ * @retval can be a combination of @ref RCC_Reset_Flag
+ */
+uint32_t HAL_RCC_GetResetSource(void)
+{
+ uint32_t reset;
+
+ /* Get all reset flags */
+ reset = RCC->CSR & RCC_RESET_FLAG_ALL;
+
+ /* Clear Reset flags */
+ RCC->CSR |= RCC_CSR_RMVF;
+
+ return reset;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup RCC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Update number of Flash wait states in line with MSI range and current
+ voltage range.
+ * @param MSI_Range MSI range value from @ref RCC_MSIRANGE_0 to @ref RCC_MSIRANGE_11
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t MSI_Range)
+{
+ uint32_t flash_clksrcfreq;
+ uint32_t msifreq;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_MSI_CLOCK_RANGE(MSI_Range));
+
+ /* MSI frequency range in Hz */
+ if (MSI_Range > RCC_MSIRANGE_11)
+ {
+ msifreq = __LL_RCC_CALC_MSI_FREQ(RCC_MSIRANGE_11);
+ }
+ else
+ {
+ msifreq = __LL_RCC_CALC_MSI_FREQ(MSI_Range);
+ }
+
+ flash_clksrcfreq = __LL_RCC_CALC_HCLK4_FREQ(msifreq, LL_RCC_GetAHB4Prescaler());
+
+#if defined(PWR_CR1_VOS)
+ return RCC_SetFlashLatency((flash_clksrcfreq / MEGA_HZ), HAL_PWREx_GetVoltageRange());
+#else
+ return RCC_SetFlashLatency((flash_clksrcfreq / MEGA_HZ), PWR_REGULATOR_VOLTAGE_SCALE1);
+#endif /* PWR_CR1_VOS */
+}
+
+
+/**
+ * @brief Update number of Flash wait states.
+ * @param Flash_ClkSrcFreq Flash Clock Source (in MHz)
+ * @param VCORE_Voltage Current Vcore voltage (PWR_REGULATOR_VOLTAGE_SCALE1 or PWR_REGULATOR_VOLTAGE_SCALE2)
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCC_SetFlashLatency(uint32_t Flash_ClkSrcFreq, uint32_t VCORE_Voltage)
+{
+ /* Flash Clock source (HCLK4) range in MHz with a VCORE is range1 */
+ const uint32_t FLASH_CLK_SRC_RANGE_VOS1[] = {18UL, 36UL, 54UL, 64UL};
+#if defined(PWR_CR1_VOS)
+ /* Flash Clock source (HCLK4) range in MHz with a VCORE is range2 */
+ const uint32_t FLASH_CLK_SRC_RANGE_VOS2[] = {6UL, 12UL, 16UL};
+#endif /* PWR_CR1_VOS */
+ /* Flash Latency range */
+ const uint32_t FLASH_LATENCY_RANGE[] = {FLASH_LATENCY_0, FLASH_LATENCY_1, FLASH_LATENCY_2, FLASH_LATENCY_3};
+ uint32_t latency = FLASH_LATENCY_0; /* default value 0WS */
+ uint32_t tickstart;
+
+#if defined(PWR_CR1_VOS)
+ if (VCORE_Voltage == PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ for (uint32_t index = 0; index < __COUNTOF(FLASH_CLK_SRC_RANGE_VOS1); index++)
+ {
+ if (Flash_ClkSrcFreq <= FLASH_CLK_SRC_RANGE_VOS1[index])
+ {
+ latency = FLASH_LATENCY_RANGE[index];
+ break;
+ }
+ }
+ }
+ else /* PWR_REGULATOR_VOLTAGE_SCALE2 */
+ {
+ for (uint32_t index = 0; index < __COUNTOF(FLASH_CLK_SRC_RANGE_VOS2); index++)
+ {
+ if (Flash_ClkSrcFreq <= FLASH_CLK_SRC_RANGE_VOS2[index])
+ {
+ latency = FLASH_LATENCY_RANGE[index];
+ break;
+ }
+ }
+ }
+#else
+ for (uint32_t index = 0; index < __COUNTOF(FLASH_CLK_SRC_RANGE_VOS1); index++)
+ {
+ if (Flash_ClkSrcFreq <= FLASH_CLK_SRC_RANGE_VOS1[index])
+ {
+ latency = FLASH_LATENCY_RANGE[index];
+ break;
+ }
+ }
+#endif /* PWR_CR1_VOS */
+
+ __HAL_FLASH_SET_LATENCY(latency);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ while (__HAL_FLASH_GET_LATENCY() != latency)
+ {
+ if ((HAL_GetTick() - tickstart) > LATENCY_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc_ex.c
new file mode 100644
index 0000000..8d4148e
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc_ex.c
@@ -0,0 +1,2328 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_rcc_ex.c
+ * @author MCD Application Team
+ * @brief Extended RCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities RCC extended peripheral:
+ * + Extended Peripheral Control functions
+ * + Extended Clock management functions
+ * + Extended Clock Recovery System Control functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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 "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RCCEx RCCEx
+ * @brief RCC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup RCCEx_Private_Constants RCCEx Private Constants
+ * @{
+ */
+#if defined(SAI1)
+#define PLLSAI1_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+#endif /* SAI1 */
+#define PLL_TIMEOUT_VALUE (2U) /* 2 ms (minimum Tick + 1) */
+
+#define CLOCKSMPS_TIMEOUT_VALUE (5000U) /* 5 s */
+
+#define __LSCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
+#define LSCO1_GPIO_PORT GPIOA
+#define LSCO1_PIN GPIO_PIN_2
+
+#define __LSCO2_CLK_ENABLE() __HAL_RCC_GPIOH_CLK_ENABLE()
+#define LSCO2_GPIO_PORT GPIOH
+#define LSCO2_PIN GPIO_PIN_3
+
+#if defined(RCC_LSCO3_SUPPORT)
+#define __LSCO3_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
+#define LSCO3_GPIO_PORT GPIOC
+#define LSCO3_PIN GPIO_PIN_12
+#endif /* RCC_LSCO3_SUPPORT */
+
+#define LSI2_TIMEOUT_VALUE (3U) /* to be adjusted with DS */
+
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup RCCEx_Private_Functions RCCEx Private Functions
+ * @{
+ */
+#if defined(SAI1)
+static HAL_StatusTypeDef RCCEx_PLLSAI1_ConfigNP(RCC_PLLSAI1InitTypeDef *PLLSAI1);
+static HAL_StatusTypeDef RCCEx_PLLSAI1_ConfigNQ(RCC_PLLSAI1InitTypeDef *PLLSAI1);
+static HAL_StatusTypeDef RCCEx_PLLSAI1_ConfigNR(RCC_PLLSAI1InitTypeDef *PLLSAI1);
+#endif /* SAI1 */
+
+static uint32_t RCC_PLL_GetFreqDomain_P(void);
+static uint32_t RCC_PLL_GetFreqDomain_Q(void);
+
+#if defined(SAI1)
+static uint32_t RCC_PLLSAI1_GetFreqDomain_R(void);
+static uint32_t RCC_PLLSAI1_GetFreqDomain_P(void);
+static uint32_t RCC_PLLSAI1_GetFreqDomain_Q(void);
+#endif /* SAI1 */
+
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
+ * @{
+ */
+
+/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the RCC Clocks
+ frequencies.
+ [..]
+ (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
+ select the RTC clock source; in this case the Backup domain will be reset in
+ order to modify the RTC Clock source, as consequence RTC registers (including
+ the backup registers) and RCC_BDCR register are set to their reset values.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the RCC extended peripherals clocks according to the specified
+ * parameters in the @ref RCC_PeriphCLKInitTypeDef.
+ * @param PeriphClkInit pointer to a @ref RCC_PeriphCLKInitTypeDef structure that
+ * contains a field PeriphClockSelection which can be a combination of the following values:
+ *
+ * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
+ * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock
+ * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
+ * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
+ * @arg @ref RCC_PERIPHCLK_RFWAKEUP RFWKP peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SMPS SMPS peripheral clock
+ *
+ *
+ * @note Care must be taken when @ref HAL_RCCEx_PeriphCLKConfig() is used to select
+ * the RTC clock source: in this case the access to Backup domain is enabled.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */
+ HAL_StatusTypeDef status = HAL_OK; /* Final status */
+
+ /* Check the parameters */
+ assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
+
+#if defined(SAI1)
+ /*-------------------------- SAI1 clock source configuration ---------------------*/
+ if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SAI1CLK(PeriphClkInit->Sai1ClockSelection));
+
+ switch (PeriphClkInit->Sai1ClockSelection)
+ {
+ case RCC_SAI1CLKSOURCE_PLL: /* PLL is used as clock source for SAI1 */
+ /* Enable SAI1 Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI1CLK);
+
+ /* SAI1 clock source config set later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI1 */
+ /* PLLSAI1 parameters N & P configuration and clock output (PLLSAI1ClockOut) */
+ ret = RCCEx_PLLSAI1_ConfigNP(&(PeriphClkInit->PLLSAI1));
+ /* SAI1 clock source config set later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_PIN: /* External clock is used as source of SAI1 clock*/
+ /* SAI1 clock source config set later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_HSI:
+
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI1 clock*/
+ __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /* SAI1 */
+
+ /*-------------------------- RTC clock source configuration ----------------------*/
+ if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
+ {
+ uint32_t rtcclocksource = LL_RCC_GetRTCClockSource();
+
+ /* Check for RTC Parameters used to output RTCCLK */
+ assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
+
+ /* Configure the clock source only if a different source is expected */
+ if (rtcclocksource != PeriphClkInit->RTCClockSelection)
+ {
+ /* Enable write access to Backup domain */
+ HAL_PWR_EnableBkUpAccess();
+
+ /* If a clock source is not yet selected */
+ if (rtcclocksource == RCC_RTCCLKSOURCE_NONE)
+ {
+ /* Directly set the configuration of the clock source selection */
+ LL_RCC_SetRTCClockSource(PeriphClkInit->RTCClockSelection);
+ }
+ else /* A clock source is already selected */
+ {
+ /* Store the content of BDCR register before the reset of Backup Domain */
+ uint32_t bdcr = LL_RCC_ReadReg(BDCR);
+
+ /* RTC Clock selection can be changed only if the Backup Domain is reset */
+ LL_RCC_ForceBackupDomainReset();
+ LL_RCC_ReleaseBackupDomainReset();
+
+ /* Set the value of the clock source selection */
+ MODIFY_REG(bdcr, RCC_BDCR_RTCSEL, PeriphClkInit->RTCClockSelection);
+
+ /* Restore the content of BDCR register */
+ LL_RCC_WriteReg(BDCR, bdcr);
+
+ /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
+ if (LL_RCC_LSE_IsEnabled() == 1U)
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while (LL_RCC_LSE_IsReady() != 1U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ ret = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+ }
+
+ /* set overall return value */
+ status = ret;
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+
+ }
+
+ /*-------------------------- USART1 clock source configuration -------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection));
+
+ /* Configure the USART1 clock source */
+ __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection);
+ }
+
+#if defined(LPUART1)
+ /*-------------------------- LPUART1 clock source configuration ------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection));
+
+ /* Configure the LPUAR1 clock source */
+ __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection);
+ }
+#endif /* LPUART1 */
+
+ /*-------------------------- LPTIM1 clock source configuration -------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == (RCC_PERIPHCLK_LPTIM1))
+ {
+ assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection));
+ __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
+ }
+
+ /*-------------------------- LPTIM2 clock source configuration -------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == (RCC_PERIPHCLK_LPTIM2))
+ {
+ assert_param(IS_RCC_LPTIM2CLK(PeriphClkInit->Lptim2ClockSelection));
+ __HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection);
+ }
+
+ /*-------------------------- I2C1 clock source configuration ---------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection));
+
+ /* Configure the I2C1 clock source */
+ __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection);
+ }
+
+#if defined(I2C3)
+ /*-------------------------- I2C3 clock source configuration ---------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C3CLKSOURCE(PeriphClkInit->I2c3ClockSelection));
+
+ /* Configure the I2C3 clock source */
+ __HAL_RCC_I2C3_CONFIG(PeriphClkInit->I2c3ClockSelection);
+ }
+#endif /* I2C3 */
+
+#if defined(USB)
+ /*-------------------------- USB clock source configuration ----------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB))
+ {
+ assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection));
+ __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
+
+ if (PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL)
+ {
+ /* Enable PLLQ output */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_USBCLK);
+ }
+#if defined(SAI1)
+ if (PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1)
+ {
+ /* PLLSAI1 parameters N & Q configuration and clock output (PLLSAI1ClockOut) */
+ ret = RCCEx_PLLSAI1_ConfigNQ(&(PeriphClkInit->PLLSAI1));
+
+ if (ret != HAL_OK)
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /* SAI1 */
+ }
+#endif /* USB */
+
+ /*-------------------------- RNG clock source configuration ----------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection));
+
+ /* Configure the RNG clock source */
+ __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection);
+
+ if (PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL)
+ {
+ /* Enable PLLQ output */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_RNGCLK);
+ }
+ }
+
+ /*-------------------------- ADC clock source configuration ----------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection));
+
+ /* Configure the ADC interface clock source */
+ __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
+
+ if (PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLL)
+ {
+ /* Enable RCC_PLL_RNGCLK output */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_ADCCLK);
+ }
+
+#if defined(SAI1)
+ if (PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1)
+ {
+ /* PLLSAI1 parameters N & R configuration and clock output (PLLSAI1ClockOut) */
+ ret = RCCEx_PLLSAI1_ConfigNR(&(PeriphClkInit->PLLSAI1));
+
+ if (ret != HAL_OK)
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /* SAI1 */
+ }
+
+ /*-------------------------- RFWKP clock source configuration ----------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RFWAKEUP) == RCC_PERIPHCLK_RFWAKEUP)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_RFWKPCLKSOURCE(PeriphClkInit->RFWakeUpClockSelection));
+
+ /* Configure the RFWKP interface clock source */
+ __HAL_RCC_RFWAKEUP_CONFIG(PeriphClkInit->RFWakeUpClockSelection);
+
+ }
+
+#if defined(RCC_SMPS_SUPPORT)
+ /*-------------------------- SMPS clock source configuration ----------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SMPS) == RCC_PERIPHCLK_SMPS)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SMPSCLKDIV(PeriphClkInit->SmpsDivSelection));
+ assert_param(IS_RCC_SMPSCLKSOURCE(PeriphClkInit->SmpsClockSelection));
+
+ /* Configure the SMPS interface clock division factor */
+ __HAL_RCC_SMPS_DIV_CONFIG(PeriphClkInit->SmpsDivSelection);
+
+ /* Configure the SMPS interface clock source */
+ __HAL_RCC_SMPS_CONFIG(PeriphClkInit->SmpsClockSelection);
+ }
+#endif /* RCC_SMPS_SUPPORT */
+
+ return status;
+}
+
+
+/**
+ * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers.
+ * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
+ * returns the configuration information for the Extended Peripherals
+ * clocks(SAI1, LPTIM1, LPTIM2, I2C1, I2C3, LPUART1,
+ * USART1, RTC, ADCx, USB, RNG, RFWKP, SMPS).
+ * @retval None
+ */
+void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ /* Set all possible values for the extended clock type parameter------------*/
+
+ PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_I2C1 | \
+ RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | \
+ RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | \
+ RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_RFWAKEUP;
+#if defined(LPUART1)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_LPUART1;
+#endif /* LPUART1 */
+
+#if defined(I2C3)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2C3;
+#endif /* I2C3 */
+
+#if defined(SAI1)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SAI1;
+#endif /* SAI1 */
+
+#if defined(USB)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USB;
+#endif /* USB */
+
+#if defined(RCC_SMPS_SUPPORT)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SMPS;
+#endif /* RCC_SMPS_SUPPORT */
+
+
+#if defined(SAI1)
+ /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLLSAI1.PLLN = LL_RCC_PLLSAI1_GetN();
+ PeriphClkInit->PLLSAI1.PLLP = LL_RCC_PLLSAI1_GetP();
+ PeriphClkInit->PLLSAI1.PLLR = LL_RCC_PLLSAI1_GetR();
+ PeriphClkInit->PLLSAI1.PLLQ = LL_RCC_PLLSAI1_GetQ();
+#endif /* SAI1 */
+
+ /* Get the USART1 clock source ---------------------------------------------*/
+ PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
+
+#if defined(LPUART1)
+ /* Get the LPUART1 clock source --------------------------------------------*/
+ PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE();
+#endif /* LPUART1 */
+
+ /* Get the I2C1 clock source -----------------------------------------------*/
+ PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
+
+#if defined(I2C3)
+ /* Get the I2C3 clock source -----------------------------------------------*/
+ PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE();
+#endif /* I2C3 */
+
+ /* Get the LPTIM1 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
+
+ /* Get the LPTIM2 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE();
+
+#if defined(SAI1)
+ /* Get the SAI1 clock source -----------------------------------------------*/
+ PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();
+#endif /* SAI1 */
+
+ /* Get the RTC clock source ------------------------------------------------*/
+ PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
+
+#if defined(USB)
+ /* Get the USB clock source ------------------------------------------------*/
+ PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
+#endif /* USB */
+
+ /* Get the RNG clock source ------------------------------------------------*/
+ PeriphClkInit->RngClockSelection = HAL_RCCEx_GetRngCLKSource();
+
+ /* Get the ADC clock source ------------------------------------------------*/
+ PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
+
+ /* Get the RFWKP clock source ----------------------------------------------*/
+ PeriphClkInit->RFWakeUpClockSelection = __HAL_RCC_GET_RFWAKEUP_SOURCE();
+
+#if defined(RCC_SMPS_SUPPORT)
+ /* Get the SMPS clock division factor --------------------------------------*/
+ PeriphClkInit->SmpsDivSelection = __HAL_RCC_GET_SMPS_DIV();
+
+ /* Get the SMPS clock source -----------------------------------------------*/
+ PeriphClkInit->SmpsClockSelection = __HAL_RCC_GET_SMPS_SOURCE();
+#endif /* RCC_SMPS_SUPPORT */
+
+}
+
+/**
+ * @brief Return the peripheral clock frequency for peripherals with clock source
+ * @note Return 0 if peripheral clock identifier not managed by this API
+ * @param PeriphClk Peripheral clock identifier
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
+ * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
+ * @arg @ref RCC_PERIPHCLK_RFWAKEUP RFWKP peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SMPS SMPS peripheral clock
+ * @retval Frequency in Hz
+ */
+uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
+{
+ uint32_t frequency = 0U;
+
+#if defined(RCC_SMPS_SUPPORT)
+ uint32_t smps_prescaler_index = ((LL_RCC_GetSMPSPrescaler()) >> RCC_SMPSCR_SMPSDIV_Pos);
+#endif /* RCC_SMPS_SUPPORT */
+
+ /* Check the parameters */
+ assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
+
+ if (PeriphClk == RCC_PERIPHCLK_RTC)
+ {
+ uint32_t rtcClockSource = LL_RCC_GetRTCClockSource();
+
+ if (rtcClockSource == LL_RCC_RTC_CLKSOURCE_LSE) /* LSE clock used as RTC clock source */
+ {
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (rtcClockSource == LL_RCC_RTC_CLKSOURCE_LSI) /* LSI clock used as RTC clock source */
+ {
+ const uint32_t temp_lsi1ready = LL_RCC_LSI1_IsReady();
+ const uint32_t temp_lsi2ready = LL_RCC_LSI2_IsReady();
+ if ((temp_lsi1ready == 1U) || (temp_lsi2ready == 1U))
+ {
+ frequency = LSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (rtcClockSource == LL_RCC_RTC_CLKSOURCE_HSE_DIV32) /* HSE clock used as RTC clock source */
+ {
+ frequency = HSE_VALUE / 32U;
+ }
+ else /* No clock used as RTC clock source */
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+#if defined(SAI1)
+ else if (PeriphClk == RCC_PERIPHCLK_SAI1)
+ {
+ switch (LL_RCC_GetSAIClockSource(LL_RCC_SAI1_CLKSOURCE))
+ {
+ case LL_RCC_SAI1_CLKSOURCE_HSI: /* HSI clock used as SAI1 clock source */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SAI1 clock source */
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ frequency = RCC_PLLSAI1_GetFreqDomain_P();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PLL: /* PLL clock used as SAI1 clock source */
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ frequency = RCC_PLL_GetFreqDomain_P();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* External input clock used as SAI1 clock source */
+ frequency = EXTERNAL_SAI1_CLOCK_VALUE;
+ break;
+ }
+ }
+#endif /* SAI1 */
+ else if (PeriphClk == RCC_PERIPHCLK_RNG)
+ {
+ uint32_t rngClockSource = HAL_RCCEx_GetRngCLKSource();
+
+ if (rngClockSource == RCC_RNGCLKSOURCE_LSI) /* LSI clock used as RNG clock source */
+ {
+ const uint32_t temp_lsi1ready = LL_RCC_LSI1_IsReady();
+ const uint32_t temp_lsi2ready = LL_RCC_LSI2_IsReady();
+ if ((temp_lsi1ready == 1U) || (temp_lsi2ready == 1U))
+ {
+ frequency = LSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (rngClockSource == RCC_RNGCLKSOURCE_LSE) /* LSE clock used as RNG clock source */
+ {
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (rngClockSource == RCC_RNGCLKSOURCE_PLL) /* PLL clock divided by 3 used as RNG clock source */
+ {
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ frequency = (RCC_PLL_GetFreqDomain_Q() / 3U);
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (rngClockSource == RCC_RNGCLKSOURCE_MSI) /* MSI clock divided by 3 used as RNG clock source */
+ {
+ if (LL_RCC_MSI_IsReady() == 1U)
+ {
+ frequency = (__LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange()) / 3U);
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+#if defined(SAI1)
+ else if (rngClockSource == RCC_RNGCLKSOURCE_PLLSAI1) /* PLLSAI1 clock used as SAI1 clock source */
+ {
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ frequency = RCC_PLLSAI1_GetFreqDomain_Q();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+#endif /* SAI1 */
+ else /* HSI48 clock divided by 3 used as RNG clock source */
+ {
+#if defined(RCC_HSI48_SUPPORT)
+ if (LL_RCC_HSI48_IsReady() == 1U)
+ {
+ frequency = HSI48_VALUE / 3U;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+#else
+ /* Nothing to do as frequency already initialized to 0U */
+#endif /* RCC_HSI48_SUPPORT */
+ }
+ }
+#if defined(USB)
+ else if (PeriphClk == RCC_PERIPHCLK_USB)
+ {
+ switch (LL_RCC_GetUSBClockSource(LL_RCC_USB_CLKSOURCE))
+ {
+#if defined(SAI1)
+ case LL_RCC_USB_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as USB clock source */
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ frequency = RCC_PLLSAI1_GetFreqDomain_Q();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+#endif /* SAI1 */
+
+ case LL_RCC_USB_CLKSOURCE_PLL: /* PLL clock used as USB clock source */
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ frequency = RCC_PLL_GetFreqDomain_Q();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ case LL_RCC_USB_CLKSOURCE_MSI: /* MSI clock used as USB clock source */
+ if (LL_RCC_MSI_IsReady() == 1U)
+ {
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* HSI48 clock used as USB clock source */
+ if (LL_RCC_HSI48_IsReady() == 1U)
+ {
+ frequency = HSI48_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+ }
+ }
+#endif /* USB */
+ else if (PeriphClk == RCC_PERIPHCLK_USART1)
+ {
+ switch (LL_RCC_GetUSARTClockSource(LL_RCC_USART1_CLKSOURCE))
+ {
+ case LL_RCC_USART1_CLKSOURCE_SYSCLK: /* USART1 Clock is System Clock */
+ frequency = HAL_RCC_GetSysClockFreq();
+ break;
+
+ case LL_RCC_USART1_CLKSOURCE_HSI: /* USART1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ case LL_RCC_USART1_CLKSOURCE_LSE: /* USART1 Clock is LSE Osc. */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* USART1 Clock is PCLK2 */
+ frequency = __LL_RCC_CALC_PCLK2_FREQ(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(),
+ LL_RCC_GetAHBPrescaler()),
+ LL_RCC_GetAPB2Prescaler());
+ break;
+ }
+ }
+#if defined(LPUART1)
+ else if (PeriphClk == RCC_PERIPHCLK_LPUART1)
+ {
+ switch (LL_RCC_GetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE))
+ {
+ case LL_RCC_LPUART1_CLKSOURCE_SYSCLK: /* LPUART1 Clock is System Clock */
+ frequency = HAL_RCC_GetSysClockFreq();
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_HSI: /* LPUART1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_LSE: /* LPUART1 Clock is LSE Osc. */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* LPUART1 Clock is PCLK1 */
+ frequency = __LL_RCC_CALC_PCLK1_FREQ(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(),
+ LL_RCC_GetAHBPrescaler()),
+ LL_RCC_GetAPB1Prescaler());
+ break;
+ }
+ }
+#endif /* LPUART1 */
+ else if (PeriphClk == RCC_PERIPHCLK_ADC)
+ {
+ switch (LL_RCC_GetADCClockSource(LL_RCC_ADC_CLKSOURCE))
+ {
+#if defined(STM32WB55xx) || defined (STM32WB5Mxx) || defined(STM32WB35xx)
+ case LL_RCC_ADC_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as ADC clock source */
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ frequency = RCC_PLLSAI1_GetFreqDomain_R();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+#elif defined(STM32WB15xx) || defined(STM32WB1Mxx)
+ case LL_RCC_ADC_CLKSOURCE_HSI: /* HSI clock used as ADC clock source */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+#endif /* STM32WB55xx || STM32WB5Mxx || STM32WB35xx */
+ case LL_RCC_ADC_CLKSOURCE_SYSCLK: /* SYSCLK clock used as ADC clock source */
+ frequency = HAL_RCC_GetSysClockFreq();
+ break;
+ case LL_RCC_ADC_CLKSOURCE_PLL: /* PLL clock used as ADC clock source */
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ frequency = RCC_PLL_GetFreqDomain_P();
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* No clock used as ADC clock source */
+ break;
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_I2C1)
+ {
+ switch (LL_RCC_GetI2CClockSource(LL_RCC_I2C1_CLKSOURCE))
+ {
+ case LL_RCC_I2C1_CLKSOURCE_SYSCLK: /* I2C1 Clock is System Clock */
+ frequency = HAL_RCC_GetSysClockFreq();
+ break;
+
+ case LL_RCC_I2C1_CLKSOURCE_HSI: /* I2C1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* I2C1 Clock is PCLK1 */
+ frequency = __LL_RCC_CALC_PCLK1_FREQ(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(),
+ LL_RCC_GetAHBPrescaler()),
+ LL_RCC_GetAPB1Prescaler());
+ break;
+ }
+ }
+#if defined(I2C3)
+ else if (PeriphClk == RCC_PERIPHCLK_I2C3)
+ {
+ switch (LL_RCC_GetI2CClockSource(LL_RCC_I2C3_CLKSOURCE))
+ {
+ case LL_RCC_I2C3_CLKSOURCE_SYSCLK: /* I2C3 Clock is System Clock */
+ frequency = HAL_RCC_GetSysClockFreq();
+ break;
+
+ case LL_RCC_I2C3_CLKSOURCE_HSI: /* I2C3 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ break;
+
+ default: /* I2C3 Clock is PCLK1 */
+ frequency = __LL_RCC_CALC_PCLK1_FREQ(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(),
+ LL_RCC_GetAHBPrescaler()),
+ LL_RCC_GetAPB1Prescaler());
+ break;
+ }
+ }
+#endif /* I2C3 */
+ else if (PeriphClk == RCC_PERIPHCLK_LPTIM1)
+ {
+ uint32_t lptimClockSource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE);
+
+ if (lptimClockSource == LL_RCC_LPTIM1_CLKSOURCE_LSI) /* LPTIM1 Clock is LSI Osc. */
+ {
+ const uint32_t temp_lsi1ready = LL_RCC_LSI1_IsReady();
+ const uint32_t temp_lsi2ready = LL_RCC_LSI2_IsReady();
+ if ((temp_lsi1ready == 1U) || (temp_lsi2ready == 1U))
+ {
+ frequency = LSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (lptimClockSource == LL_RCC_LPTIM1_CLKSOURCE_HSI) /* LPTIM1 Clock is HSI Osc. */
+ {
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (lptimClockSource == LL_RCC_LPTIM1_CLKSOURCE_LSE) /* LPTIM1 Clock is LSE Osc. */
+ {
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else /* LPTIM1 Clock is PCLK1 */
+ {
+ frequency = __LL_RCC_CALC_PCLK1_FREQ(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(),
+ LL_RCC_GetAHBPrescaler()),
+ LL_RCC_GetAPB1Prescaler());
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_LPTIM2)
+ {
+ uint32_t lptimClockSource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE);
+
+ if (lptimClockSource == LL_RCC_LPTIM2_CLKSOURCE_LSI) /* LPTIM2 Clock is LSI Osc. */
+ {
+ const uint32_t temp_lsi1ready = LL_RCC_LSI1_IsReady();
+ const uint32_t temp_lsi2ready = LL_RCC_LSI2_IsReady();
+ if ((temp_lsi1ready == 1U) || (temp_lsi2ready == 1U))
+ {
+ frequency = LSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (lptimClockSource == LL_RCC_LPTIM2_CLKSOURCE_HSI) /* LPTIM2 Clock is HSI Osc. */
+ {
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (lptimClockSource == LL_RCC_LPTIM2_CLKSOURCE_LSE) /* LPTIM2 Clock is LSE Osc. */
+ {
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else /* LPTIM2 Clock is PCLK1 */
+ {
+ frequency = __LL_RCC_CALC_PCLK1_FREQ(__LL_RCC_CALC_HCLK1_FREQ(HAL_RCC_GetSysClockFreq(),
+ LL_RCC_GetAHBPrescaler()),
+ LL_RCC_GetAPB1Prescaler());
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_RFWAKEUP)
+ {
+ uint32_t rfwkpClockSource = LL_RCC_GetRFWKPClockSource();
+
+ if (rfwkpClockSource == LL_RCC_RFWKP_CLKSOURCE_LSE) /* LSE clock used as RF Wakeup clock source */
+ {
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ frequency = LSE_VALUE;
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (rfwkpClockSource == LL_RCC_RFWKP_CLKSOURCE_HSE_DIV1024) /* HSE clock used as RF Wakeup clock source */
+ {
+ frequency = HSE_VALUE / 1024U;
+ }
+ else /* No clock used as RF Wakeup clock source */
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+#if defined(RCC_SMPS_SUPPORT)
+ else if (PeriphClk == RCC_PERIPHCLK_SMPS)
+ {
+ uint32_t smpsClockSource = LL_RCC_GetSMPSClockSource();
+
+ if (smpsClockSource == LL_RCC_SMPS_CLKSOURCE_STATUS_HSI) /* SMPS Clock source is HSI Osc. */
+ {
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ frequency = HSI_VALUE / SmpsPrescalerTable[smps_prescaler_index][0];
+ frequency = frequency >> 1U; /* Systematic Div by 2 */
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (smpsClockSource == LL_RCC_SMPS_CLKSOURCE_STATUS_HSE) /* SMPS Clock source is HSE Osc. */
+ {
+ if (LL_RCC_HSE_IsReady() == 1U)
+ {
+ frequency = HSE_VALUE / SmpsPrescalerTable[smps_prescaler_index][5];
+ frequency = frequency >> 1U; /* Systematic Div by 2 */
+ }
+ else
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+ else if (smpsClockSource == LL_RCC_SMPS_CLKSOURCE_STATUS_MSI) /* SMPS Clock source is MSI Osc. */
+ {
+ switch (LL_RCC_MSI_GetRange())
+ {
+ case LL_RCC_MSIRANGE_8:
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_8) / SmpsPrescalerTable[smps_prescaler_index][4];
+ break;
+ case LL_RCC_MSIRANGE_9:
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_9) / SmpsPrescalerTable[smps_prescaler_index][3];
+ break;
+ case LL_RCC_MSIRANGE_10:
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_10) / SmpsPrescalerTable[smps_prescaler_index][2];
+ break;
+ case LL_RCC_MSIRANGE_11:
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_11) / SmpsPrescalerTable[smps_prescaler_index][1];
+ break;
+ default:
+ break;
+ }
+ frequency = frequency >> 1U; /* Systematic Div by 2 */
+ }
+ else /* SMPS has no Clock */
+ {
+ /* Nothing to do as frequency already initialized to 0U */
+ }
+ }
+#endif /* RCC_SMPS_SUPPORT */
+
+ return (frequency);
+}
+
+/**
+ * @brief Return the RNG clock source
+ * @retval The RNG clock source can be one of the following values:
+ * @arg @ref RCC_RNGCLKSOURCE_HSI48 HSI48 clock divided by 3 selected as RNG clock
+ * @arg @ref RCC_RNGCLKSOURCE_PLL PLL "Q" clock divided by 3 selected as RNG clock
+ * @arg @ref RCC_RNGCLKSOURCE_MSI MSI clock divided by 3 selected as RNG clock
+ * @arg @ref RCC_RNGCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock selected as RNG clock (*)
+ * @arg @ref RCC_RNGCLKSOURCE_LSI LSI clock selected as RNG clock
+ * @arg @ref RCC_RNGCLKSOURCE_LSE LSE clock selected as RNG clock
+ *
+ * (*) Value not defined in all devices.
+ *
+ */
+uint32_t HAL_RCCEx_GetRngCLKSource(void)
+{
+ uint32_t rng_clock_source = LL_RCC_GetRNGClockSource(LL_RCC_RNG_CLKSOURCE);
+ uint32_t clk48_clock_source;
+
+ /* RNG clock source originates from 48 MHz RC oscillator */
+ if (rng_clock_source == RCC_RNGCLKSOURCE_CLK48)
+ {
+ clk48_clock_source = LL_RCC_GetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE);
+ rng_clock_source = (CLK48_MASK | clk48_clock_source);
+ }
+
+ return rng_clock_source;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
+ * @brief Extended Clock management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended clock management functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the
+ activation or deactivation of MSI PLL-mode, PLLSAI1, PLLSAI12, LSE CSS,
+ Low speed clock output and clock after wake-up from STOP mode.
+@endverbatim
+ * @{
+ */
+
+#if defined(SAI1)
+/**
+ * @brief Enable PLLSAI1.
+ * @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that
+ * contains the configuration information for the PLLSAI1
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLN_VALUE(PLLSAI1Init->PLLN));
+ assert_param(IS_RCC_PLLP_VALUE(PLLSAI1Init->PLLP));
+ assert_param(IS_RCC_PLLQ_VALUE(PLLSAI1Init->PLLQ));
+ assert_param(IS_RCC_PLLR_VALUE(PLLSAI1Init->PLLR));
+ assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1Init->PLLSAI1ClockOut));
+
+ /* Disable the PLLSAI1 */
+ __HAL_RCC_PLLSAI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready to be updated */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Multiplication factor N */
+ /* Configure the PLLSAI1 Division factors P, Q and R */
+ __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLN, PLLSAI1Init->PLLP, PLLSAI1Init->PLLQ, PLLSAI1Init->PLLR);
+ /* Configure the PLLSAI1 Clock output(s) */
+ __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut);
+
+ /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
+ __HAL_RCC_PLLSAI1_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready */
+ while (LL_RCC_PLLSAI1_IsReady() != 1U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable PLLSAI1.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Disable the PLLSAI1 */
+ __HAL_RCC_PLLSAI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ /* Disable the PLLSAI1 Clock outputs */
+ __HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1_SAI1CLK | RCC_PLLSAI1_USBCLK | RCC_PLLSAI1_ADCCLK);
+
+ return status;
+}
+#endif /* SAI1 */
+
+/***********************************************************************************************/
+
+/**
+ * @brief Configure the oscillator clock source for wakeup from Stop and CSS backup clock.
+ * @param WakeUpClk Wakeup clock
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_STOP_WAKEUPCLOCK_MSI MSI oscillator selection
+ * @arg @ref RCC_STOP_WAKEUPCLOCK_HSI HSI oscillator selection
+ * @note This function shall not be called after the Clock Security System on HSE has been
+ * enabled.
+ * @retval None
+ */
+void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk)
+{
+ assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk));
+
+ __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk);
+}
+
+/**
+ * @brief Enable the LSE Clock Security System.
+ * @note Prior to enable the LSE Clock Security System, LSE oscillator is to be enabled
+ * with HAL_RCC_OscConfig() and the LSE oscillator clock is to be selected as RTC
+ * clock with HAL_RCCEx_PeriphCLKConfig().
+ * @retval None
+ */
+void HAL_RCCEx_EnableLSECSS(void)
+{
+ LL_RCC_LSE_EnableCSS();
+}
+
+/**
+ * @brief Disable the LSE Clock Security System.
+ * @note LSE Clock Security System can only be disabled after a LSE failure detection.
+ * @retval None
+ */
+void HAL_RCCEx_DisableLSECSS(void)
+{
+ LL_RCC_LSE_DisableCSS();
+
+ /* Disable LSE CSS IT if any */
+ __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
+}
+
+/**
+ * @brief Enable the LSE Clock Security System Interrupt & corresponding EXTI line.
+ * @note LSE Clock Security System Interrupt is mapped on RTC EXTI line 18
+ * @retval None
+ */
+void HAL_RCCEx_EnableLSECSS_IT(void)
+{
+ /* Enable LSE CSS */
+ LL_RCC_LSE_EnableCSS();
+
+ /* Enable LSE CSS IT */
+ __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
+
+ /* Enable IT on EXTI Line 18 */
+ __HAL_RCC_LSECSS_EXTI_ENABLE_IT();
+ __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
+}
+
+/**
+ * @brief Handle the RCC LSE Clock Security System interrupt request.
+ * @retval None
+ */
+void HAL_RCCEx_LSECSS_IRQHandler(void)
+{
+ /* Check RCC LSE CSSF flag */
+ if (__HAL_RCC_GET_IT(RCC_IT_LSECSS))
+ {
+ /* RCC LSE Clock Security System interrupt user callback */
+ HAL_RCCEx_LSECSS_Callback();
+
+ /* Clear RCC LSE CSS pending bit */
+ __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
+ }
+}
+
+/**
+ * @brief RCCEx LSE Clock Security System interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_LSECSS_Callback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RCCEx_LSECSS_Callback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Select the clock source to output on LSCO1 pin(PA2) or LSC02 pin (PH3) or LSCO3 pin (PC12).
+ * @note PA2, PH3 or PC12 should be configured in alternate function mode.
+ * @param RCC_LSCOx specifies the output direction for the clock source.
+ * @arg @ref RCC_LSCO1 Clock source to output on LSCO1 pin(PA2)
+ * @arg @ref RCC_LSCO2 Clock source to output on LSCO2 pin(PH3)
+ * @arg @ref RCC_LSCO3 Clock source to output on LSCO3 pin(PC12)
+ * @param RCC_LSCOSource specifies the clock source to output.
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
+ * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
+ * @retval None
+ * @note LSCO should be disable with @ref HAL_RCCEx_DisableLSCO
+ */
+void HAL_RCCEx_LSCOConfig(uint32_t RCC_LSCOx, uint32_t RCC_LSCOSource)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ FlagStatus backupchanged;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_LSCO(RCC_LSCOx));
+ assert_param(IS_RCC_LSCOSOURCE(RCC_LSCOSource));
+
+ /* Common GPIO init parameters */
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+
+ /* RCC_LSCO1 */
+ if (RCC_LSCOx == RCC_LSCO1)
+ {
+ /* LSCO1 Clock Enable */
+ __LSCO1_CLK_ENABLE();
+ /* Configure the LSCO1 pin in alternate function mode */
+ GPIO_InitStruct.Pin = LSCO1_PIN;
+ GPIO_InitStruct.Alternate = GPIO_AF0_LSCO;
+ HAL_GPIO_Init(LSCO1_GPIO_PORT, &GPIO_InitStruct);
+ }
+ else if (RCC_LSCOx == RCC_LSCO2)
+ {
+ /* LSCO2 Clock Enable */
+ __LSCO2_CLK_ENABLE();
+ /* Configure the LSCO2 pin in alternate function mode */
+ GPIO_InitStruct.Pin = LSCO2_PIN;
+ GPIO_InitStruct.Alternate = GPIO_AF0_LSCO;
+ HAL_GPIO_Init(LSCO2_GPIO_PORT, &GPIO_InitStruct);
+
+ }
+#if defined(RCC_LSCO3_SUPPORT)
+ else if (RCC_LSCOx == RCC_LSCO3)
+ {
+ /* LSCO3 Clock Enable */
+ __LSCO3_CLK_ENABLE();
+ /* Configure the LSCO3 pin in alternate function mode */
+ GPIO_InitStruct.Pin = LSCO3_PIN;
+ GPIO_InitStruct.Alternate = GPIO_AF6_LSCO;
+ HAL_GPIO_Init(LSCO3_GPIO_PORT, &GPIO_InitStruct);
+ }
+#endif /* RCC_LSCO3_SUPPORT */
+ else
+ {
+ ;
+ }
+
+ /* Update LSCOSEL clock source in Backup Domain control register */
+ if (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
+ {
+ HAL_PWR_EnableBkUpAccess();
+ backupchanged = SET;
+ }
+ else
+ {
+ backupchanged = RESET;
+ }
+
+ MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL | RCC_BDCR_LSCOEN, RCC_LSCOSource | RCC_BDCR_LSCOEN);
+
+ if (backupchanged == SET)
+ {
+ HAL_PWR_DisableBkUpAccess();
+ }
+
+}
+
+/**
+ * @brief Select the Low Speed clock source to output on LSCO pin (PA2).
+ * @param LSCOSource specifies the Low Speed clock source to output.
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
+ * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
+ * @retval None
+ */
+void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource)
+{
+ /* Check the parameters */
+ assert_param(IS_RCC_LSCOSOURCE(LSCOSource));
+
+ /* Update LSCO selection according to parameter and enable LSCO */
+ MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL, LSCOSource | RCC_BDCR_LSCOEN);
+}
+
+/**
+ * @brief Disable the Low Speed clock output.
+ * @retval None
+ */
+void HAL_RCCEx_DisableLSCO(void)
+{
+ LL_RCC_LSCO_Disable();
+}
+
+/**
+ * @brief Enable the PLL-mode of the MSI.
+ * @note Prior to enable the PLL-mode of the MSI for automatic hardware
+ * calibration LSE oscillator is to be enabled with @ref HAL_RCC_OscConfig().
+ * @retval None
+ */
+void HAL_RCCEx_EnableMSIPLLMode(void)
+{
+ LL_RCC_MSI_EnablePLLMode() ;
+}
+
+/**
+ * @brief Disable the PLL-mode of the MSI.
+ * @note PLL-mode of the MSI is automatically reset when LSE oscillator is disabled.
+ * @retval None
+ */
+void HAL_RCCEx_DisableMSIPLLMode(void)
+{
+ LL_RCC_MSI_DisablePLLMode() ;
+}
+
+/**
+ * @brief Set trimming value
+ * @param OscillatorType Specifies the oscillator to be trimmed
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_OSCILLATORTYPE_LSI2 LSI2 oscillator selected.
+ * When disabling and re-enabling the LSI2 there is no need for re-trimming
+ * Trimming is only needed once after a NRST reset.
+ * Trimming values comes from factory trimmed flash location (0x1FFF7548).
+ * @note The LSI2 oscillator must be disabled before calling this trimming function through @ref HAL_RCC_OscConfig
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_TrimOsc(uint32_t OscillatorType)
+{
+#define FTLSI2TRIM (0xFUL)
+ HAL_StatusTypeDef status = HAL_OK;
+
+ assert_param(IS_RCC_TRIMOSC(OscillatorType));
+
+ if (OscillatorType == RCC_OSCILLATORTYPE_LSI2)
+ {
+ if (LL_RCC_LSI2_IsReady() == 1U)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Copy the LSI2 trimming information from the factory trimmed Flash location */
+ uint32_t factoryTrimming = ((*(uint32_t *)(0x1FFF7548)) & FTLSI2TRIM);
+ LL_RCC_LSI2_SetTrimming(factoryTrimming);
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ return status;
+}
+
+/**
+ * @}
+ */
+
+#if defined(CRS)
+/** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions
+ * @brief Extended Clock Recovery System Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Clock Recovery System Control functions #####
+ ===============================================================================
+ [..]
+ For devices with Clock Recovery System feature (CRS), RCC Extended HAL driver can be used as follows:
+
+ (#) In System clock config, HSI48 needs to be enabled
+
+ (#) Enable CRS clock in IP MSP init which will use CRS functions
+
+ (#) Call CRS functions as follows:
+ (##) Prepare synchronization configuration necessary for HSI48 calibration
+ (+++) Default values can be set for frequency Error Measurement (reload and error limit)
+ and also HSI48 oscillator smooth trimming.
+ (+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate
+ directly reload value with target and synchronization frequencies values
+ (##) Call function HAL_RCCEx_CRSConfig which
+ (+++) Resets CRS registers to their default values.
+ (+++) Configures CRS registers with synchronization configuration
+ (+++) Enables automatic calibration and frequency error counter feature
+ Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the
+ periodic USB SOF will not be generated by the host. No SYNC signal will therefore be
+ provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock
+ precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs
+ should be used as SYNC signal.
+
+ (##) A polling function is provided to wait for complete synchronization
+ (+++) Call function HAL_RCCEx_CRSWaitSynchronization()
+ (+++) According to CRS status, user can decide to adjust again the calibration or continue
+ application if synchronization is OK
+
+ (#) User can retrieve information related to synchronization in calling function
+ HAL_RCCEx_CRSGetSynchronizationInfo()
+
+ (#) Regarding synchronization status and synchronization information, user can try a new calibration
+ in changing synchronization configuration and call again HAL_RCCEx_CRSConfig.
+ Note: When the SYNC event is detected during the downcounting phase (before reaching the zero value),
+ it means that the actual frequency is lower than the target (and so, that the TRIM value should be
+ incremented), while when it is detected during the upcounting phase it means that the actual frequency
+ is higher (and that the TRIM value should be decremented).
+
+ (#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go
+ through CRS Handler (CRS_IRQn/CRS_IRQHandler)
+ (++) Call function HAL_RCCEx_CRSConfig()
+ (++) Enable CRS_IRQn (thanks to NVIC functions)
+ (++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT)
+ (++) Implement CRS status management in the following user callbacks called from
+ HAL_RCCEx_CRS_IRQHandler():
+ (+++) HAL_RCCEx_CRS_SyncOkCallback()
+ (+++) HAL_RCCEx_CRS_SyncWarnCallback()
+ (+++) HAL_RCCEx_CRS_ExpectedSyncCallback()
+ (+++) HAL_RCCEx_CRS_ErrorCallback()
+
+ (#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate().
+ This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler)
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start automatic synchronization for polling mode
+ * @param pInit Pointer on RCC_CRSInitTypeDef structure
+ * @retval None
+ */
+void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit)
+{
+ uint32_t value;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler));
+ assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source));
+ assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity));
+ assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue));
+ assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue));
+ assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue));
+
+ /* CONFIGURATION */
+
+ /* Before configuration, reset CRS registers to their default values*/
+ __HAL_RCC_CRS_FORCE_RESET();
+ __HAL_RCC_CRS_RELEASE_RESET();
+
+ /* Set the SYNCDIV[2:0] bits according to Prescaler value */
+ /* Set the SYNCSRC[1:0] bits according to Source value */
+ /* Set the SYNCSPOL bit according to Polarity value */
+ value = (pInit->Prescaler | pInit->Source | pInit->Polarity);
+ /* Set the RELOAD[15:0] bits according to ReloadValue value */
+ value |= pInit->ReloadValue;
+ /* Set the FELIM[7:0] bits according to ErrorLimitValue value */
+ value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_Pos);
+ WRITE_REG(CRS->CFGR, value);
+
+ /* Adjust HSI48 oscillator smooth trimming */
+ /* Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value */
+ MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos));
+
+ /* START AUTOMATIC SYNCHRONIZATION*/
+
+ /* Enable Automatic trimming & Frequency error counter */
+ SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN);
+}
+
+/**
+ * @brief Generate the software synchronization event
+ * @retval None
+ */
+void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)
+{
+ LL_CRS_GenerateEvent_SWSYNC();
+}
+
+/**
+ * @brief Return synchronization info
+ * @param pSynchroInfo Pointer on @ref RCC_CRSSynchroInfoTypeDef structure
+ * @retval None
+ */
+void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo)
+{
+ /* Check the parameter */
+ assert_param(pSynchroInfo != (void *)NULL);
+
+ /* Get the reload value */
+ pSynchroInfo->ReloadValue = LL_CRS_GetReloadCounter();
+
+ /* Get HSI48 oscillator smooth trimming */
+ pSynchroInfo->HSI48CalibrationValue = LL_CRS_GetHSI48SmoothTrimming();
+
+ /* Get Frequency error capture */
+ pSynchroInfo->FreqErrorCapture = LL_CRS_GetFreqErrorCapture();
+
+ /* Get Frequency error direction */
+ pSynchroInfo->FreqErrorDirection = LL_CRS_GetFreqErrorDirection();
+}
+
+/**
+ * @brief Wait for CRS Synchronization status.
+ * @param Timeout Duration of the timeout
+ * @note Timeout is based on the maximum time to receive a SYNC event based on synchronization
+ * frequency.
+ * @note If Timeout set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned.
+ * @retval Combination of Synchronization status
+ * This parameter can be a combination of the following values:
+ * @arg @ref RCC_CRS_TIMEOUT
+ * @arg @ref RCC_CRS_SYNCOK
+ * @arg @ref RCC_CRS_SYNCWARN
+ * @arg @ref RCC_CRS_SYNCERR
+ * @arg @ref RCC_CRS_SYNCMISS
+ * @arg @ref RCC_CRS_TRIMOVF
+ */
+uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)
+{
+ uint32_t crsstatus = RCC_CRS_NONE;
+ uint32_t tickstart;
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait for CRS flag or timeout detection */
+ do
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ crsstatus = RCC_CRS_TIMEOUT;
+ }
+ }
+ /* Check CRS SYNCOK flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK))
+ {
+ /* CRS SYNC event OK */
+ crsstatus |= RCC_CRS_SYNCOK;
+
+ /* Clear CRS SYNC event OK bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK);
+ }
+
+ /* Check CRS SYNCWARN flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN))
+ {
+ /* CRS SYNC warning */
+ crsstatus |= RCC_CRS_SYNCWARN;
+
+ /* Clear CRS SYNCWARN bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN);
+ }
+
+ /* Check CRS TRIM overflow flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF))
+ {
+ /* CRS SYNC Error */
+ crsstatus |= RCC_CRS_TRIMOVF;
+
+ /* Clear CRS Error bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF);
+ }
+
+ /* Check CRS Error flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR))
+ {
+ /* CRS SYNC Error */
+ crsstatus |= RCC_CRS_SYNCERR;
+
+ /* Clear CRS Error bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR);
+ }
+
+ /* Check CRS SYNC Missed flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS))
+ {
+ /* CRS SYNC Missed */
+ crsstatus |= RCC_CRS_SYNCMISS;
+
+ /* Clear CRS SYNC Missed bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS);
+ }
+
+ /* Check CRS Expected SYNC flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC))
+ {
+ /* frequency error counter reached a zero value */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC);
+ }
+ } while (RCC_CRS_NONE == crsstatus);
+
+ return crsstatus;
+}
+
+/**
+ * @brief Handle the Clock Recovery System interrupt request.
+ * @retval None
+ */
+void HAL_RCCEx_CRS_IRQHandler(void)
+{
+ uint32_t crserror = RCC_CRS_NONE;
+ /* Get current IT flags and IT sources values */
+ uint32_t itflags = READ_REG(CRS->ISR);
+ uint32_t itsources = READ_REG(CRS->CR);
+
+ /* Check CRS SYNCOK flag */
+ if (((itflags & RCC_CRS_FLAG_SYNCOK) != 0U) && ((itsources & RCC_CRS_IT_SYNCOK) != 0U))
+ {
+ /* Clear CRS SYNC event OK flag */
+ LL_CRS_ClearFlag_SYNCOK();
+
+ /* user callback */
+ HAL_RCCEx_CRS_SyncOkCallback();
+ }
+ /* Check CRS SYNCWARN flag */
+ else if (((itflags & RCC_CRS_FLAG_SYNCWARN) != 0U) && ((itsources & RCC_CRS_IT_SYNCWARN) != 0U))
+ {
+ /* Clear CRS SYNCWARN flag */
+ LL_CRS_ClearFlag_SYNCWARN();
+
+ /* user callback */
+ HAL_RCCEx_CRS_SyncWarnCallback();
+ }
+ /* Check CRS Expected SYNC flag */
+ else if (((itflags & RCC_CRS_FLAG_ESYNC) != 0U) && ((itsources & RCC_CRS_IT_ESYNC) != 0U))
+ {
+ /* frequency error counter reached a zero value */
+ LL_CRS_ClearFlag_ESYNC();
+
+ /* user callback */
+ HAL_RCCEx_CRS_ExpectedSyncCallback();
+ }
+ /* Check CRS Error flags */
+ else
+ {
+ if (((itflags & RCC_CRS_FLAG_ERR) != 0U) && ((itsources & RCC_CRS_IT_ERR) != 0U))
+ {
+ if ((itflags & RCC_CRS_FLAG_SYNCERR) != 0U)
+ {
+ crserror |= RCC_CRS_SYNCERR;
+ }
+ if ((itflags & RCC_CRS_FLAG_SYNCMISS) != 0U)
+ {
+ crserror |= RCC_CRS_SYNCMISS;
+ }
+ if ((itflags & RCC_CRS_FLAG_TRIMOVF) != 0U)
+ {
+ crserror |= RCC_CRS_TRIMOVF;
+ }
+
+ /* Clear CRS Error flags */
+ LL_CRS_ClearFlag_ERR();
+
+ /* user error callback */
+ HAL_RCCEx_CRS_ErrorCallback(crserror);
+ }
+ }
+}
+
+/**
+ * @brief RCCEx Clock Recovery System SYNCOK interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_SyncOkCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief RCCEx Clock Recovery System SYNCWARN interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_SyncWarnCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief RCCEx Clock Recovery System Expected SYNC interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief RCCEx Clock Recovery System Error interrupt callback.
+ * @param Error Combination of Error status.
+ * This parameter can be a combination of the following values:
+ * @arg @ref RCC_CRS_SYNCERR
+ * @arg @ref RCC_CRS_SYNCMISS
+ * @arg @ref RCC_CRS_TRIMOVF
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Error);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+#endif /* CRS */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RCCEx_Private_Functions
+ * @{
+ */
+
+#if defined(SAI1)
+/**
+ * @brief Configure the parameters N & P of PLLSAI1 and enable PLLSAI1 output clock(s).
+ * @param PLLSAI1 pointer to an RCC_PLLSAI1InitTypeDef structure that
+ * contains the configuration parameters N & P as well as PLLSAI1 output clock(s)
+ *
+ * @note PLLSAI1 is temporary disable to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLLSAI1_ConfigNP(RCC_PLLSAI1InitTypeDef *PLLSAI1)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLN_VALUE(PLLSAI1->PLLN));
+ assert_param(IS_RCC_PLLP_VALUE(PLLSAI1->PLLP));
+ assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1->PLLSAI1ClockOut));
+
+ /* Disable the PLLSAI1 */
+ __HAL_RCC_PLLSAI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready to be updated */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Multiplication factor N */
+ __HAL_RCC_PLLSAI1_MULN_CONFIG(PLLSAI1->PLLN);
+
+ /* Configure the PLLSAI1 Division factor P */
+ __HAL_RCC_PLLSAI1_DIVP_CONFIG(PLLSAI1->PLLP);
+
+ /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
+ __HAL_RCC_PLLSAI1_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready */
+ while (LL_RCC_PLLSAI1_IsReady() != 1U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Clock output(s) */
+ __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1->PLLSAI1ClockOut);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Configure the parameters N & Q of PLLSAI1 and enable PLLSAI1 output clock(s).
+ * @param PLLSAI1 pointer to an RCC_PLLSAI1InitTypeDef structure that
+ * contains the configuration parameters N & Q as well as PLLSAI1 output clock(s)
+ *
+ * @note PLLSAI1 is temporary disable to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLLSAI1_ConfigNQ(RCC_PLLSAI1InitTypeDef *PLLSAI1)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLN_VALUE(PLLSAI1->PLLN));
+ assert_param(IS_RCC_PLLQ_VALUE(PLLSAI1->PLLQ));
+ assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1->PLLSAI1ClockOut));
+
+ /* Disable the PLLSAI1 */
+ __HAL_RCC_PLLSAI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready to be updated */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Multiplication factor N */
+ __HAL_RCC_PLLSAI1_MULN_CONFIG(PLLSAI1->PLLN);
+ /* Configure the PLLSAI1 Division factor Q */
+ __HAL_RCC_PLLSAI1_DIVQ_CONFIG(PLLSAI1->PLLQ);
+
+ /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
+ __HAL_RCC_PLLSAI1_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready */
+ while (LL_RCC_PLLSAI1_IsReady() != 1U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Clock output(s) */
+ __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1->PLLSAI1ClockOut);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Configure the parameters N & R of PLLSAI1 and enable PLLSAI1 output clock(s).
+ * @param PLLSAI1 pointer to an RCC_PLLSAI1InitTypeDef structure that
+ * contains the configuration parameters N & R as well as PLLSAI1 output clock(s)
+ *
+ * @note PLLSAI1 is temporary disable to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLLSAI1_ConfigNR(RCC_PLLSAI1InitTypeDef *PLLSAI1)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLN_VALUE(PLLSAI1->PLLN));
+ assert_param(IS_RCC_PLLR_VALUE(PLLSAI1->PLLR));
+ assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1->PLLSAI1ClockOut));
+
+ /* Disable the PLLSAI1 */
+ __HAL_RCC_PLLSAI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready to be updated */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Multiplication factor N */
+ __HAL_RCC_PLLSAI1_MULN_CONFIG(PLLSAI1->PLLN);
+ /* Configure the PLLSAI1 Division factor R */
+ __HAL_RCC_PLLSAI1_DIVR_CONFIG(PLLSAI1->PLLR);
+
+ /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
+ __HAL_RCC_PLLSAI1_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready */
+ while (LL_RCC_PLLSAI1_IsReady() != 1U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the PLLSAI1 Clock output(s) */
+ __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1->PLLSAI1ClockOut);
+ }
+ }
+
+ return status;
+}
+#endif /* SAI1 */
+
+/**
+ * @brief Return PLL clock (PLLPCLK) frequency used for SAI domain
+ * @retval PLLPCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLL_GetFreqDomain_P(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI Value / PLLM) * PLLN
+ SAI Domain clock = PLL_VCO / PLLP
+ */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLCLK_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLL_GetN(), LL_RCC_PLL_GetP());
+}
+
+/**
+ * @brief Return PLL clock (PLLQCLK) frequency used for 48 MHz domain
+ * @retval PLLQCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLL_GetFreqDomain_Q(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLN
+ 48M Domain clock = PLL_VCO / PLLQ
+ */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLCLK_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLL_GetN(), LL_RCC_PLL_GetQ());
+}
+
+#if defined(SAI1)
+/**
+ * @brief Return PLLSAI1 clock (PLLSAI1RCLK) frequency used for ADC domain
+ * @retval PLLSAI1RCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLLSAI1_GetFreqDomain_R(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLSAI1N */
+ /* 48M Domain clock = PLLSAI1_VCO / PLLSAI1R */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLSAI1_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetR());
+}
+
+/**
+ * @brief Return PLLSAI1 clock (PLLSAI1PCLK) frequency used for SAI domain
+ * @retval PLLSAI1PCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLLSAI1_GetFreqDomain_P(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLSAI1N */
+ /* SAI Domain clock = PLLSAI1_VCO / PLLSAI1P */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLSAI1_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetP());
+}
+
+/**
+ * @brief Return PLLSAI1 clock (PLLSAI1QCLK) frequency used for 48Mhz domain
+ * @retval PLLSAI1QCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLLSAI1_GetFreqDomain_Q(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLSAI1N */
+ /* 48M Domain clock = PLLSAI1_VCO / PLLSAI1Q */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLSAI1_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetQ());
+}
+#endif /* SAI1 */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc.c
new file mode 100644
index 0000000..b5ba9b2
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc.c
@@ -0,0 +1,1945 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_rtc.c
+ * @author MCD Application Team
+ * @brief RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real-Time Clock (RTC) peripheral:
+ * + Initialization and de-initialization functions
+ * + Calendar (Time and Date) configuration functions
+ * + Alarms (Alarm A and Alarm B) configuration functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### RTC and Backup Domain Operating Condition #####
+ ==============================================================================
+ [..] The real-time clock (RTC) and the RTC backup registers can be powered
+ from the VBAT voltage when the main VDD supply is powered off.
+ To retain the content of the RTC backup registers and supply the RTC when
+ VDD is turned off, VBAT pin can be connected to an optional standby
+ voltage supplied by a battery or by another source.
+
+ [..] To allow the RTC operating even when the main digital supply (VDD) is turned
+ off, the VBAT pin powers the following blocks:
+ (#) The RTC
+ (#) The LSE oscillator
+ (#) PC13 to PC15 I/Os, plus PA0 and PC12 I/Os (when available)
+
+ [..] When the backup domain is supplied by VDD (analog switch connected to VDD),
+ the following pins are available:
+ (#) PC14 and PC15 can be used as either GPIO or LSE pins
+ (#) PC13 can be used as a GPIO or as the RTC_AF1 pin
+ (#) PA0 can be used as a GPIO or as the RTC_AF2 pin
+ (#) PC12 can be used as a GPIO or as the RTC_AF3 pin
+
+ [..] When the backup domain is supplied by VBAT (analog switch connected to VBAT
+ because VDD is not present), the following pins are available:
+ (#) PC14 and PC15 can be used as LSE pins only
+ (#) PC13 can be used as the RTC_AF1 pin
+ (#) PA0 can be used as the RTC_AF2 pin
+ (#) PC12 can be used as the RTC_AF3 pin
+
+ ##### Backup Domain Reset #####
+ ==================================================================
+ [..] The backup domain reset sets all RTC registers and the RCC_BDCR register
+ to their reset values.
+ [..] A backup domain reset is generated when one of the following events occurs:
+ (#) Software reset, triggered by setting the BDRST bit in the
+ RCC Backup domain control register (RCC_BDCR).
+ (#) VDD or VBAT power on, if both supplies have previously been powered off.
+ (#) Tamper detection event resets all data backup registers.
+
+ ##### Backup Domain Access #####
+ ==================================================================
+ [..] After reset, the backup domain (RTC registers and RTC backup data registers)
+ is protected against possible unwanted write accesses.
+ [..] To enable access to the RTC Domain and RTC registers, proceed as follows:
+ (+) Enable the Power Controller (PWR) APB1 interface clock using the
+ __HAL_RCC_PWR_CLK_ENABLE() macro.
+ (+) Enable access to RTC domain using the HAL_PWR_EnableBkUpAccess() function.
+ (+) Select the RTC clock source using the __HAL_RCC_RTC_CONFIG() macro.
+ (+) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() macro.
+
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) Enable the RTC domain access (see description in the section above).
+ (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** Time and Date configuration ***
+ ===================================
+ [..]
+ (+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
+ and HAL_RTC_SetDate() functions.
+ (+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate()
+ functions.
+ (+) To manage the RTC summer or winter time change, use the following
+ functions:
+ (++) HAL_RTC_DST_Add1Hour() or HAL_RTC_DST_Sub1Hour to add or subtract
+ 1 hour from the calendar time.
+ (++) HAL_RTC_DST_SetStoreOperation() or HAL_RTC_DST_ClearStoreOperation
+ to memorize whether the time change has been performed or not.
+
+ *** Alarm configuration ***
+ ===========================
+ [..]
+ (+) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function.
+ You can also configure the RTC Alarm with interrupt mode using the
+ HAL_RTC_SetAlarm_IT() function.
+ (+) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function.
+
+ ##### RTC and low power modes #####
+ ==================================================================
+ [..] The MCU can be woken up from a low power mode by an RTC alternate
+ function.
+ [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B),
+ RTC wakeup, RTC tamper event detection and RTC timestamp event detection.
+ These RTC alternate functions can wake up the system from the Stop and
+ Standby low power modes.
+ [..] The system can also wake up from low power modes without depending
+ on an external interrupt (Auto-wakeup mode), by using the RTC alarm
+ or the RTC wakeup events.
+ [..] The RTC provides a programmable time base for waking up from the
+ Stop or Standby mode at regular intervals.
+ Wakeup from STOP and STANDBY modes is possible only when the RTC clock
+ source is LSE or LSI.
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ When the compilation define USE_HAL_RTC_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all
+ callbacks are set to the corresponding weak functions.
+ This is the recommended configuration in order to optimize memory/code
+ consumption footprint/performances.
+ [..]
+ The compilation define USE_HAL_RTC_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Function HAL_RTC_RegisterCallback() to register an interrupt callback.
+ [..]
+ Function HAL_RTC_RegisterCallback() allows to register following callbacks:
+ (+) AlarmAEventCallback : RTC Alarm A Event callback.
+ (+) AlarmBEventCallback : RTC Alarm B Event callback.
+ (+) TimeStampEventCallback : RTC Timestamp Event callback.
+ (+) WakeUpTimerEventCallback : RTC WakeUpTimer Event callback.
+ (+) Tamper1EventCallback : RTC Tamper 1 Event callback. (*)
+ (+) Tamper2EventCallback : RTC Tamper 2 Event callback.
+ (+) Tamper3EventCallback : RTC Tamper 3 Event callback. (*)
+ (+) MspInitCallback : RTC MspInit callback.
+ (+) MspDeInitCallback : RTC MspDeInit callback.
+
+ (*) value not applicable to all devices.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+ [..]
+ Use function HAL_RTC_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ HAL_RTC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) AlarmAEventCallback : RTC Alarm A Event callback.
+ (+) AlarmBEventCallback : RTC Alarm B Event callback.
+ (+) TimeStampEventCallback : RTC Timestamp Event callback.
+ (+) WakeUpTimerEventCallback : RTC WakeUpTimer Event callback.
+ (+) Tamper1EventCallback : RTC Tamper 1 Event callback. (*)
+ (+) Tamper2EventCallback : RTC Tamper 2 Event callback.
+ (+) Tamper3EventCallback : RTC Tamper 3 Event callback. (*)
+ (+) MspInitCallback : RTC MspInit callback.
+ (+) MspDeInitCallback : RTC MspDeInit callback.
+
+ (*) value not applicable to all devices.
+ [..]
+ By default, after the HAL_RTC_Init() and when the state is HAL_RTC_STATE_RESET,
+ all callbacks are set to the corresponding weak functions:
+ examples AlarmAEventCallback(), TimeStampEventCallback().
+ Exception done for MspInit() and MspDeInit() callbacks that are reset to the
+ legacy weak function in the HAL_RTC_Init()/HAL_RTC_DeInit() only when these
+ callbacks are null (not registered beforehand).
+ If not, MspInit() or MspDeInit() are not null, HAL_RTC_Init()/HAL_RTC_DeInit()
+ keep and use the user MspInit()/MspDeInit() callbacks (registered beforehand).
+ [..]
+ Callbacks can be registered/unregistered in HAL_RTC_STATE_READY state only.
+ Exception done for MspInit() and MspDeInit() that can be registered/unregistered
+ in HAL_RTC_STATE_READY or HAL_RTC_STATE_RESET state.
+ Thus registered (user) MspInit()/MspDeInit() callbacks can be used during the
+ Init/DeInit.
+ In that case first register the MspInit()/MspDeInit() user callbacks using
+ HAL_RTC_RegisterCallback() before calling HAL_RTC_DeInit() or HAL_RTC_Init()
+ functions.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RTC RTC
+ * @brief RTC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup RTC_Exported_Functions RTC Exported Functions
+ * @{
+ */
+
+/** @defgroup RTC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to initialize and configure the
+ RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable
+ RTC registers Write protection, enter and exit the RTC initialization mode,
+ RTC registers synchronization check and reference clock detection enable.
+ (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base.
+ It is split into 2 programmable prescalers to minimize power consumption.
+ (++) A 7-bit asynchronous prescaler and a 15-bit synchronous prescaler.
+ (++) When both prescalers are used, it is recommended to configure the
+ asynchronous prescaler to a high value to minimize power consumption.
+ (#) All RTC registers are Write protected. Writing to the RTC registers
+ is enabled by writing a key into the Write Protection register, RTC_WPR.
+ (#) To configure the RTC Calendar, user application should enter
+ initialization mode. In this mode, the calendar counter is stopped
+ and its value can be updated. When the initialization sequence is
+ complete, the calendar restarts counting after 4 RTCCLK cycles.
+ (#) To read the calendar through the shadow registers after Calendar
+ initialization, calendar update or after wakeup from low power modes
+ the software must first clear the RSF flag. The software must then
+ wait until it is set again before reading the calendar, which means
+ that the calendar registers have been correctly copied into the
+ RTC_TR and RTC_DR shadow registers. The HAL_RTC_WaitForSynchro() function
+ implements the above software sequence (RSF clear and RSF check).
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the RTC peripheral
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check RTC handler validity */
+ if (hrtc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
+ assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat));
+ assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv));
+ assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv));
+ assert_param(IS_RTC_OUTPUT(hrtc->Init.OutPut));
+ assert_param(IS_RTC_OUTPUT_REMAP(hrtc->Init.OutPutRemap));
+ assert_param(IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity));
+ assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType));
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ if (hrtc->State == HAL_RTC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrtc->Lock = HAL_UNLOCKED;
+
+ hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
+ hrtc->AlarmBEventCallback = HAL_RTCEx_AlarmBEventCallback; /* Legacy weak AlarmBEventCallback */
+ hrtc->TimeStampEventCallback = HAL_RTCEx_TimeStampEventCallback; /* Legacy weak TimeStampEventCallback */
+ hrtc->WakeUpTimerEventCallback = HAL_RTCEx_WakeUpTimerEventCallback; /* Legacy weak WakeUpTimerEventCallback */
+#if defined(RTC_TAMPER1_SUPPORT)
+ hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
+#endif /* RTC_TAMPER1_SUPPORT */
+ hrtc->Tamper2EventCallback = HAL_RTCEx_Tamper2EventCallback; /* Legacy weak Tamper2EventCallback */
+#if defined(RTC_TAMPER3_SUPPORT)
+ hrtc->Tamper3EventCallback = HAL_RTCEx_Tamper3EventCallback; /* Legacy weak Tamper3EventCallback */
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ if (hrtc->MspInitCallback == NULL)
+ {
+ hrtc->MspInitCallback = HAL_RTC_MspInit;
+ }
+ /* Init the low level hardware */
+ hrtc->MspInitCallback(hrtc);
+
+ if (hrtc->MspDeInitCallback == NULL)
+ {
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ }
+ }
+#else /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ if (hrtc->State == HAL_RTC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrtc->Lock = HAL_UNLOCKED;
+
+ /* Initialize RTC MSP */
+ HAL_RTC_MspInit(hrtc);
+ }
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Check whether the calendar needs to be initialized */
+ if (__HAL_RTC_IS_CALENDAR_INITIALIZED(hrtc) == 0U)
+ {
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Enter Initialization mode */
+ status = RTC_EnterInitMode(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Clear RTC_CR FMT, OSEL and POL Bits */
+ hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL));
+ /* Set RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity);
+
+ /* Configure the RTC PRER */
+ hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv);
+ hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << RTC_PRER_PREDIV_A_Pos);
+
+ /* Exit Initialization mode */
+ status = RTC_ExitInitMode(hrtc);
+ }
+
+ if (status == HAL_OK)
+ {
+#if defined(RTC_OR_ALARMOUTTYPE)
+ hrtc->Instance->OR &= (uint32_t)~(RTC_OUTPUT_TYPE_PUSHPULL | RTC_OUTPUT_REMAP_POS1);
+ hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType | hrtc->Init.OutPutRemap);
+#else
+ hrtc->Instance->OR &= (uint32_t)~RTC_OUTPUT_REMAP_POS1;
+ hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutRemap);
+#endif /* RTC_OR_ALARMOUTTYPE */
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+ }
+ else
+ {
+ /* The calendar is already initialized */
+ status = HAL_OK;
+ }
+
+ if (status == HAL_OK)
+ {
+ hrtc->State = HAL_RTC_STATE_READY;
+ }
+
+ return status;
+}
+
+/**
+ * @brief DeInitializes the RTC peripheral
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note This function does not reset the RTC Backup Data registers.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Enter Initialization mode */
+ status = RTC_EnterInitMode(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Reset RTC registers */
+ hrtc->Instance->TR = 0x00000000U;
+ hrtc->Instance->DR = (RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0);
+ hrtc->Instance->CR = 0x00000000U;
+ hrtc->Instance->WUTR = RTC_WUTR_WUT;
+ hrtc->Instance->PRER = (uint32_t)(RTC_PRER_PREDIV_A | 0x000000FFU);
+ hrtc->Instance->ALRMAR = 0x00000000U;
+ hrtc->Instance->ALRMBR = 0x00000000U;
+ hrtc->Instance->CALR = 0x00000000U;
+ hrtc->Instance->SHIFTR = 0x00000000U;
+ hrtc->Instance->ALRMASSR = 0x00000000U;
+ hrtc->Instance->ALRMBSSR = 0x00000000U;
+
+ /* Exit Initialization mode */
+ status = RTC_ExitInitMode(hrtc);
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Reset Tamper and alternate functions configuration register */
+ hrtc->Instance->TAMPCR = 0x00000000U;
+
+ /* Reset Option register */
+ hrtc->Instance->OR = 0x00000000U;
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ if (hrtc->MspDeInitCallback == NULL)
+ {
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ }
+
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ hrtc->MspDeInitCallback(hrtc);
+#else /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ /* De-Initialize RTC MSP */
+ HAL_RTC_MspDeInit(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+
+ hrtc->State = HAL_RTC_STATE_RESET;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Registers a User RTC Callback
+ * To be used instead of the weak predefined callback
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
+ * @arg @ref HAL_RTC_ALARM_B_EVENT_CB_ID Alarm B Event Callback ID
+ * @arg @ref HAL_RTC_TIMESTAMP_EVENT_CB_ID Timestamp Event Callback ID
+ * @arg @ref HAL_RTC_WAKEUPTIMER_EVENT_CB_ID Wakeup Timer Event Callback ID
+ * @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Event Callback ID (*)
+ * @arg @ref HAL_RTC_TAMPER2_EVENT_CB_ID Tamper 2 Event Callback ID
+ * @arg @ref HAL_RTC_TAMPER3_EVENT_CB_ID Tamper 3 Event Callback ID (*)
+ * @arg @ref HAL_RTC_MSPINIT_CB_ID MSP Init callback ID
+ * @arg @ref HAL_RTC_MSPDEINIT_CB_ID MSP DeInit callback ID
+ *
+ * (*) value not applicable to all devices.
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hrtc);
+
+ if (HAL_RTC_STATE_READY == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_ALARM_A_EVENT_CB_ID :
+ hrtc->AlarmAEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_ALARM_B_EVENT_CB_ID :
+ hrtc->AlarmBEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_TIMESTAMP_EVENT_CB_ID :
+ hrtc->TimeStampEventCallback = pCallback;
+ break;
+
+ case HAL_RTC_WAKEUPTIMER_EVENT_CB_ID :
+ hrtc->WakeUpTimerEventCallback = pCallback;
+ break;
+
+#if defined(RTC_TAMPER1_SUPPORT)
+ case HAL_RTC_TAMPER1_EVENT_CB_ID :
+ hrtc->Tamper1EventCallback = pCallback;
+ break;
+#endif /* RTC_TAMPER1_SUPPORT */
+
+ case HAL_RTC_TAMPER2_EVENT_CB_ID :
+ hrtc->Tamper2EventCallback = pCallback;
+ break;
+
+#if defined(RTC_TAMPER3_SUPPORT)
+ case HAL_RTC_TAMPER3_EVENT_CB_ID :
+ hrtc->Tamper3EventCallback = pCallback;
+ break;
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_RTC_STATE_RESET == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = pCallback;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+/**
+ * @brief Unregisters an RTC Callback
+ * RTC callback is redirected to the weak predefined callback
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
+ * @arg @ref HAL_RTC_ALARM_B_EVENT_CB_ID Alarm B Event Callback ID
+ * @arg @ref HAL_RTC_TIMESTAMP_EVENT_CB_ID Timestamp Event Callback ID
+ * @arg @ref HAL_RTC_WAKEUPTIMER_EVENT_CB_ID Wakeup Timer Event Callback ID
+ * @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Event Callback ID (*)
+ * @arg @ref HAL_RTC_TAMPER2_EVENT_CB_ID Tamper 2 Event Callback ID
+ * @arg @ref HAL_RTC_TAMPER3_EVENT_CB_ID Tamper 3 Event Callback ID (*)
+ * @arg @ref HAL_RTC_MSPINIT_CB_ID MSP Init callback ID
+ * @arg @ref HAL_RTC_MSPDEINIT_CB_ID MSP DeInit callback ID
+ *
+ * (*) value not applicable to all devices.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hrtc);
+
+ if (HAL_RTC_STATE_READY == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_ALARM_A_EVENT_CB_ID :
+ hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
+ break;
+
+ case HAL_RTC_ALARM_B_EVENT_CB_ID :
+ hrtc->AlarmBEventCallback = HAL_RTCEx_AlarmBEventCallback; /* Legacy weak AlarmBEventCallback */
+ break;
+
+ case HAL_RTC_TIMESTAMP_EVENT_CB_ID :
+ hrtc->TimeStampEventCallback = HAL_RTCEx_TimeStampEventCallback; /* Legacy weak TimeStampEventCallback */
+ break;
+
+ case HAL_RTC_WAKEUPTIMER_EVENT_CB_ID :
+ hrtc->WakeUpTimerEventCallback = HAL_RTCEx_WakeUpTimerEventCallback; /* Legacy weak WakeUpTimerEventCallback */
+ break;
+
+#if defined(RTC_TAMPER1_SUPPORT)
+ case HAL_RTC_TAMPER1_EVENT_CB_ID :
+ hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
+ break;
+#endif /* RTC_TAMPER1_SUPPORT */
+
+ case HAL_RTC_TAMPER2_EVENT_CB_ID :
+ hrtc->Tamper2EventCallback = HAL_RTCEx_Tamper2EventCallback; /* Legacy weak Tamper2EventCallback */
+ break;
+
+#if defined(RTC_TAMPER3_SUPPORT)
+ case HAL_RTC_TAMPER3_EVENT_CB_ID :
+ hrtc->Tamper3EventCallback = HAL_RTCEx_Tamper3EventCallback; /* Legacy weak Tamper3EventCallback */
+ break;
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = HAL_RTC_MspInit;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_RTC_STATE_RESET == hrtc->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_RTC_MSPINIT_CB_ID :
+ hrtc->MspInitCallback = HAL_RTC_MspInit;
+ break;
+
+ case HAL_RTC_MSPDEINIT_CB_ID :
+ hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+
+/**
+ * @brief Initializes the RTC MSP.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the RTC MSP.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group2 RTC Time and Date functions
+ * @brief RTC Time and Date functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Time and Date functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Time and Date features
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets RTC current time.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTime Pointer to Time structure
+ * @note DayLightSaving and StoreOperation interfaces are deprecated.
+ * To manage Daylight Saving Time, please use HAL_RTC_DST_xxx functions.
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
+{
+ uint32_t tmpreg = 0U;
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving));
+ assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if (Format == RTC_FORMAT_BIN)
+ {
+ if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(sTime->Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
+ }
+ else
+ {
+ sTime->TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(sTime->Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sTime->Minutes));
+ assert_param(IS_RTC_SECONDS(sTime->Seconds));
+
+ tmpreg = (uint32_t)(( (uint32_t)RTC_ByteToBcd2(sTime->Hours) << RTC_TR_HU_Pos) | \
+ ( (uint32_t)RTC_ByteToBcd2(sTime->Minutes) << RTC_TR_MNU_Pos) | \
+ ( (uint32_t)RTC_ByteToBcd2(sTime->Seconds)) | \
+ (((uint32_t)sTime->TimeFormat) << RTC_TR_PM_Pos));
+ }
+ else
+ {
+ if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sTime->Hours)));
+ assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
+ }
+ else
+ {
+ sTime->TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
+ }
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
+ tmpreg = (((uint32_t)(sTime->Hours) << RTC_TR_HU_Pos) | \
+ ((uint32_t)(sTime->Minutes) << RTC_TR_MNU_Pos) | \
+ ((uint32_t) sTime->Seconds) | \
+ ((uint32_t)(sTime->TimeFormat) << RTC_TR_PM_Pos));
+ }
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Enter Initialization mode */
+ status = RTC_EnterInitMode(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Set the RTC_TR register */
+ hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK);
+
+ /* Clear the bits to be configured (Deprecated. Use HAL_RTC_DST_xxx functions instead) */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_BKP;
+
+ /* Configure the RTC_CR register (Deprecated. Use HAL_RTC_DST_xxx functions instead) */
+ hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation);
+
+ /* Exit Initialization mode */
+ status = RTC_ExitInitMode(hrtc);
+ }
+
+ if (status == HAL_OK)
+ {
+ hrtc->State = HAL_RTC_STATE_READY;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+/**
+ * @brief Gets RTC current time.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTime Pointer to Time structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You can use SubSeconds and SecondFraction (sTime structure fields
+ * returned) to convert SubSeconds value in second fraction ratio with
+ * time unit following generic formula:
+ * Second fraction ratio * time_unit =
+ * [(SecondFraction - SubSeconds) / (SecondFraction + 1)] * time_unit
+ * This conversion can be performed only if no shift operation is pending
+ * (ie. SHFP=0) when PREDIV_S >= SS
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the
+ * values in the higher-order calendar shadow registers to ensure
+ * consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers
+ * until current date is read to ensure consistency between the time and
+ * date values.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get subseconds value from the corresponding register */
+ sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR);
+
+ /* Get SecondFraction structure field from the corresponding register field*/
+ sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S);
+
+ /* Get the TR register */
+ tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK);
+
+ /* Fill the structure fields with the read parameters */
+ sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> RTC_TR_HU_Pos);
+ sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos);
+ sTime->Seconds = (uint8_t)( tmpreg & (RTC_TR_ST | RTC_TR_SU));
+ sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> RTC_TR_PM_Pos);
+
+ /* Check the input parameters format */
+ if (Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the time structure parameters to Binary format */
+ sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours);
+ sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes);
+ sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets RTC current date.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sDate Pointer to date structure
+ * @param Format specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg = 0U;
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if ((Format == RTC_FORMAT_BIN) && ((sDate->Month & 0x10U) == 0x10U))
+ {
+ sDate->Month = (uint8_t)((sDate->Month & (uint8_t)~(0x10U)) + (uint8_t)0x0AU);
+ }
+
+ assert_param(IS_RTC_WEEKDAY(sDate->WeekDay));
+
+ if (Format == RTC_FORMAT_BIN)
+ {
+ assert_param(IS_RTC_YEAR(sDate->Year));
+ assert_param(IS_RTC_MONTH(sDate->Month));
+ assert_param(IS_RTC_DATE(sDate->Date));
+
+ datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year) << RTC_DR_YU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sDate->Month) << RTC_DR_MU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sDate->Date)) | \
+ ((uint32_t)sDate->WeekDay << RTC_DR_WDU_Pos));
+ }
+ else
+ {
+ assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year)));
+ assert_param(IS_RTC_MONTH(RTC_Bcd2ToByte(sDate->Month)));
+ assert_param(IS_RTC_DATE(RTC_Bcd2ToByte(sDate->Date)));
+
+ datetmpreg = ((((uint32_t)sDate->Year) << RTC_DR_YU_Pos) | \
+ (((uint32_t)sDate->Month) << RTC_DR_MU_Pos) | \
+ ((uint32_t) sDate->Date) | \
+ (((uint32_t)sDate->WeekDay) << RTC_DR_WDU_Pos));
+ }
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Enter Initialization mode */
+ status = RTC_EnterInitMode(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Set the RTC_DR register */
+ hrtc->Instance->DR = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK);
+
+ /* Exit Initialization mode */
+ status = RTC_ExitInitMode(hrtc);
+ }
+
+ if (status == HAL_OK)
+ {
+ hrtc->State = HAL_RTC_STATE_READY;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+/**
+ * @brief Gets RTC current date.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sDate Pointer to Date structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the
+ * values in the higher-order calendar shadow registers to ensure
+ * consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers
+ * until current date is read to ensure consistency between the time and
+ * date values.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get the DR register */
+ datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK);
+
+ /* Fill the structure fields with the read parameters */
+ sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos);
+ sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos);
+ sDate->Date = (uint8_t) (datetmpreg & (RTC_DR_DT | RTC_DR_DU));
+ sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> RTC_DR_WDU_Pos);
+
+ /* Check the input parameters format */
+ if (Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the date structure parameters to Binary format */
+ sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year);
+ sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month);
+ sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group3 RTC Alarm functions
+ * @brief RTC Alarm functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Alarm functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Alarm feature
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Sets the specified RTC Alarm.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sAlarm Pointer to Alarm structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note The Alarm register can only be written when the corresponding Alarm
+ * is disabled (Use the HAL_RTC_DeactivateAlarm()).
+ * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
+{
+ uint32_t tickstart = 0U;
+ uint32_t tmpreg = 0U;
+ uint32_t subsecondtmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(sAlarm->Alarm));
+ assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask));
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ /* Change RTC state to BUSY */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Check the data format (binary or BCD) and store the Alarm time and date
+ configuration accordingly */
+ if (Format == RTC_FORMAT_BIN)
+ {
+ if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
+ assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
+
+ if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay));
+ }
+
+ tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ else
+ {
+ if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
+
+ if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+
+ tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t) sAlarm->AlarmTime.Seconds) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t) sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t) sAlarm->AlarmMask));
+ }
+
+ /* Store the Alarm subseconds configuration */
+ subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | \
+ (uint32_t)(sAlarm->AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ if (sAlarm->Alarm == RTC_ALARM_A)
+ {
+ /* Disable Alarm A */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* In case interrupt mode is used, the interrupt source must be disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
+
+ /* Clear Alarm A flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRAWF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure Alarm A register */
+ hrtc->Instance->ALRMAR = (uint32_t)tmpreg;
+ /* Configure Alarm A Subseconds register */
+ hrtc->Instance->ALRMASSR = subsecondtmpreg;
+ /* Enable Alarm A */
+ __HAL_RTC_ALARMA_ENABLE(hrtc);
+ }
+ else
+ {
+ /* Disable Alarm B */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* In case interrupt mode is used, the interrupt source must be disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB);
+
+ /* Clear Alarm B flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRBWF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure Alarm B register */
+ hrtc->Instance->ALRMBR = (uint32_t)tmpreg;
+ /* Configure Alarm B Subseconds register */
+ hrtc->Instance->ALRMBSSR = subsecondtmpreg;
+ /* Enable Alarm B */
+ __HAL_RTC_ALARMB_ENABLE(hrtc);
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state back to READY */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets the specified RTC Alarm with Interrupt.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sAlarm Pointer to Alarm structure
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note The Alarm register can only be written when the corresponding Alarm
+ * is disabled (Use the HAL_RTC_DeactivateAlarm()).
+ * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
+{
+ __IO uint32_t count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U);
+ uint32_t tmpreg = 0U;
+ uint32_t subsecondtmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(sAlarm->Alarm));
+ assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask));
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ /* Change RTC state to BUSY */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Check the data format (binary or BCD) and store the Alarm time and date
+ configuration accordingly */
+ if (Format == RTC_FORMAT_BIN)
+ {
+ if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
+ assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
+
+ if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay));
+ }
+
+ tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ else
+ {
+ if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U)
+ {
+ assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00U;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
+
+ if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay)));
+ }
+
+ tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \
+ ((uint32_t)(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \
+ ((uint32_t) sAlarm->AlarmTime.Seconds) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_ALRMAR_PM_Pos) | \
+ ((uint32_t)(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \
+ ((uint32_t) sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t) sAlarm->AlarmMask));
+ }
+
+ /* Store the Alarm subseconds configuration */
+ subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | \
+ (uint32_t)(sAlarm->AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ if (sAlarm->Alarm == RTC_ALARM_A)
+ {
+ /* Disable Alarm A */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* Clear Alarm A flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ /* Wait till RTC ALRAWF flag is set and if timeout is reached exit */
+ do
+ {
+ count = count - 1U;
+ if (count == 0U)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ } while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U);
+
+ /* Configure Alarm A register */
+ hrtc->Instance->ALRMAR = (uint32_t)tmpreg;
+ /* Configure Alarm A Subseconds register */
+ hrtc->Instance->ALRMASSR = subsecondtmpreg;
+ /* Enable Alarm A */
+ __HAL_RTC_ALARMA_ENABLE(hrtc);
+ /* Enable Alarm A interrupt */
+ __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRA);
+ }
+ else
+ {
+ /* Disable Alarm B */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* Clear Alarm B flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* Reload the counter */
+ count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U);
+
+ /* Wait till RTC ALRBWF flag is set and if timeout is reached exit */
+ do
+ {
+ count = count - 1U;
+ if (count == 0U)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ } while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U);
+
+ /* Configure Alarm B register */
+ hrtc->Instance->ALRMBR = (uint32_t)tmpreg;
+ /* Configure Alarm B Subseconds register */
+ hrtc->Instance->ALRMBSSR = subsecondtmpreg;
+ /* Enable Alarm B */
+ __HAL_RTC_ALARMB_ENABLE(hrtc);
+ /* Enable Alarm B interrupt */
+ __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRB);
+ }
+
+ /* Enable and configure the EXTI line associated to the RTC Alarm interrupt */
+ __HAL_RTC_ALARM_EXTI_ENABLE_IT();
+ __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state back to READY */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates the specified RTC Alarm.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Alarm Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: Alarm A
+ * @arg RTC_ALARM_B: Alarm B
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm)
+{
+ uint32_t tickstart = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALARM(Alarm));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ if (Alarm == RTC_ALARM_A)
+ {
+ /* Disable Alarm A */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* In case interrupt mode is used, the interrupt source must be disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRAWF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Disable Alarm B */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* In case interrupt mode is used, the interrupt source must be disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRBWF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets the RTC Alarm value and masks.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sAlarm Pointer to Date structure
+ * @param Alarm Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: Alarm A
+ * @arg RTC_ALARM_B: Alarm B
+ * @param Format Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format)
+{
+ uint32_t tmpreg = 0U;
+ uint32_t subsecondtmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(Alarm));
+
+ if (Alarm == RTC_ALARM_A)
+ {
+ sAlarm->Alarm = RTC_ALARM_A;
+
+ tmpreg = (uint32_t)(hrtc->Instance->ALRMAR);
+ subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMASSR) & RTC_ALRMASSR_SS);
+ }
+ else
+ {
+ sAlarm->Alarm = RTC_ALARM_B;
+
+ tmpreg = (uint32_t)(hrtc->Instance->ALRMBR);
+ subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMBSSR) & RTC_ALRMBSSR_SS);
+ }
+
+ /* Fill the structure with the read parameters */
+ sAlarm->AlarmTime.Hours = (uint8_t) ((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> RTC_ALRMAR_HU_Pos);
+ sAlarm->AlarmTime.Minutes = (uint8_t) ((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> RTC_ALRMAR_MNU_Pos);
+ sAlarm->AlarmTime.Seconds = (uint8_t) ( tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU));
+ sAlarm->AlarmTime.TimeFormat = (uint8_t) ((tmpreg & RTC_ALRMAR_PM) >> RTC_TR_PM_Pos);
+ sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg;
+ sAlarm->AlarmDateWeekDay = (uint8_t) ((tmpreg & (RTC_ALRMAR_DT | RTC_ALRMAR_DU)) >> RTC_ALRMAR_DU_Pos);
+ sAlarm->AlarmDateWeekDaySel = (uint32_t) (tmpreg & RTC_ALRMAR_WDSEL);
+ sAlarm->AlarmMask = (uint32_t) (tmpreg & RTC_ALARMMASK_ALL);
+
+ if (Format == RTC_FORMAT_BIN)
+ {
+ sAlarm->AlarmTime.Hours = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours);
+ sAlarm->AlarmTime.Minutes = RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes);
+ sAlarm->AlarmTime.Seconds = RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds);
+ sAlarm->AlarmDateWeekDay = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles Alarm interrupt request.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Clear the EXTI flag associated to the RTC Alarm interrupt */
+ __HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
+
+ /* Get the Alarm A interrupt source enable status */
+ if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != 0U)
+ {
+ /* Get the pending status of the Alarm A Interrupt */
+ if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != 0U)
+ {
+ /* Clear the Alarm A interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ /* Alarm A callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->AlarmAEventCallback(hrtc);
+#else
+ HAL_RTC_AlarmAEventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Get the Alarm B interrupt source enable status */
+ if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != 0U)
+ {
+ /* Get the pending status of the Alarm B Interrupt */
+ if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != 0U)
+ {
+ /* Clear the Alarm B interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* Alarm B callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->AlarmBEventCallback(hrtc);
+#else
+ HAL_RTCEx_AlarmBEventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Alarm A callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTC_AlarmAEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handles Alarm A Polling request.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRAF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Alarm flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group4 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Wait for RTC Time and Date Synchronization
+ (+) Manage RTC Summer or Winter time change
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ * @note The RTC Resynchronization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @note To read the calendar through the shadow registers after Calendar
+ * initialization, calendar update or after wakeup from low power modes
+ * the software must first clear the RSF flag.
+ * The software must then wait until it is set again before reading
+ * the calendar, which means that the calendar registers have been
+ * correctly copied into the RTC_TR and RTC_DR shadow registers.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart = 0U;
+
+ /* Clear RSF flag, keep reserved bits at reset values (setting other flags has no effect) */
+ hrtc->Instance->ISR = ((uint32_t)(RTC_RSF_MASK & RTC_ISR_RESERVED_MASK));
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait the registers to be synchronised */
+ while ((hrtc->Instance->ISR & RTC_ISR_RSF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Daylight Saving Time, adds one hour to the calendar in one
+ * single operation without going through the initialization procedure.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTC_DST_Add1Hour(RTC_HandleTypeDef *hrtc)
+{
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ SET_BIT(hrtc->Instance->CR, RTC_CR_ADD1H);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+}
+
+/**
+ * @brief Daylight Saving Time, subtracts one hour from the calendar in one
+ * single operation without going through the initialization procedure.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTC_DST_Sub1Hour(RTC_HandleTypeDef *hrtc)
+{
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ SET_BIT(hrtc->Instance->CR, RTC_CR_SUB1H);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+}
+
+/**
+ * @brief Daylight Saving Time, sets the store operation bit.
+ * @note It can be used by the software in order to memorize the DST status.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTC_DST_SetStoreOperation(RTC_HandleTypeDef *hrtc)
+{
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ SET_BIT(hrtc->Instance->CR, RTC_CR_BKP);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+}
+
+/**
+ * @brief Daylight Saving Time, clears the store operation bit.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTC_DST_ClearStoreOperation(RTC_HandleTypeDef *hrtc)
+{
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+ CLEAR_BIT(hrtc->Instance->CR, RTC_CR_BKP);
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+}
+
+/**
+ * @brief Daylight Saving Time, reads the store operation bit.
+ * @param hrtc RTC handle
+ * @retval operation see RTC_StoreOperation_Definitions
+ */
+uint32_t HAL_RTC_DST_ReadStoreOperation(RTC_HandleTypeDef *hrtc)
+{
+ return READ_BIT(hrtc->Instance->CR, RTC_CR_BKP);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group5 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Get RTC state
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Returns the RTC state.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL state
+ */
+HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc)
+{
+ return hrtc->State;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Enters the RTC Initialization mode.
+ * @note The RTC Initialization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check that Initialization mode is not already set */
+ if (READ_BIT(hrtc->Instance->ISR, RTC_ISR_INITF) == 0U)
+ {
+ /* Set INIT bit to enter Initialization mode */
+ SET_BIT(hrtc->Instance->ISR, RTC_ISR_INIT);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC is in INIT state and if timeout is reached exit */
+ while ((READ_BIT(hrtc->Instance->ISR, RTC_ISR_INITF) == 0U) && (status != HAL_ERROR))
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Exits the RTC Initialization mode.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Clear INIT bit to exit Initialization mode */
+ CLEAR_BIT(hrtc->Instance->ISR, RTC_ISR_INIT);
+
+ /* If CR_BYPSHAD bit = 0, wait for synchro */
+ if (READ_BIT(hrtc->Instance->CR, RTC_CR_BYPSHAD) == 0U)
+ {
+ if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Converts a 2-digit number from decimal to BCD format.
+ * @param number decimal-formatted number (from 0 to 99) to be converted
+ * @retval Converted byte
+ */
+uint8_t RTC_ByteToBcd2(uint8_t number)
+{
+ uint32_t bcdhigh = 0U;
+
+ while (number >= 10U)
+ {
+ bcdhigh++;
+ number -= 10U;
+ }
+
+ return ((uint8_t)(bcdhigh << 4U) | number);
+}
+
+/**
+ * @brief Converts a 2-digit number from BCD to decimal format.
+ * @param number BCD-formatted number (from 00 to 99) to be converted
+ * @retval Converted word
+ */
+uint8_t RTC_Bcd2ToByte(uint8_t number)
+{
+ uint32_t tens = 0U;
+ tens = (((uint32_t)number & 0xF0U) >> 4U) * 10U;
+ return (uint8_t)(tens + ((uint32_t)number & 0x0FU));
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RTC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c
new file mode 100644
index 0000000..c7944f3
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c
@@ -0,0 +1,2104 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_rtc_ex.c
+ * @author MCD Application Team
+ * @brief Extended RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real-Time Clock (RTC) Extended peripheral:
+ * + RTC Timestamp functions
+ * + RTC Tamper functions
+ * + RTC Wakeup functions
+ * + Extended Control functions
+ * + Extended RTC features functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) Enable the RTC domain access.
+ (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** RTC Wakeup configuration ***
+ ================================
+ [..]
+ (+) To configure the RTC Wakeup Clock source and Counter use the
+ HAL_RTCEx_SetWakeUpTimer() function.
+ You can also configure the RTC Wakeup timer in interrupt mode using the
+ HAL_RTCEx_SetWakeUpTimer_IT() function.
+ (+) To read the RTC Wakeup Counter register, use the HAL_RTCEx_GetWakeUpTimer()
+ function.
+
+ *** Timestamp configuration ***
+ ===============================
+ [..]
+ (+) To configure the RTC Timestamp use the HAL_RTCEx_SetTimeStamp() function.
+ You can also configure the RTC Timestamp with interrupt mode using the
+ HAL_RTCEx_SetTimeStamp_IT() function.
+ (+) To read the RTC Timestamp Time and Date register, use the
+ HAL_RTCEx_GetTimeStamp() function.
+ (+) The Timestamp alternate function is mapped to RTC_AF1 (PC13).
+
+ *** Internal Timestamp configuration ***
+ ===============================
+ [..]
+ (+) To enable the RTC internal Timestamp use the HAL_RTCEx_SetInternalTimeStamp()
+ function.
+ (+) To read the RTC Timestamp Time and Date register, use the HAL_RTCEx_GetTimeStamp()
+ function.
+
+ *** Tamper configuration ***
+ ============================
+ [..]
+ (+) To enable the RTC Tamper and configure the Tamper filter count, trigger
+ Edge or Level according to the Tamper filter value (if equal to 0 Edge
+ else Level), sampling frequency, NoErase, MaskFlag, precharge or
+ discharge and Pull-UP use the HAL_RTCEx_SetTamper() function.
+ You can configure RTC Tamper in interrupt mode using HAL_RTCEx_SetTamper_IT()
+ function.
+ (+) The default configuration of the Tamper erases the backup registers.
+ To avoid this, enable the NoErase field on the RTC_TAMPCR register.
+ (+) The TAMPER1 alternate function is mapped to RTC_AF1 (PC13).
+ (+) The TAMPER2 alternate function is mapped to RTC_AF2 (PA0).
+ (+) The TAMPER3 alternate function is mapped to RTC_AF3 (PC12).
+
+ *** Backup Data Registers configuration ***
+ ===========================================
+ [..]
+ (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite()
+ function.
+ (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead()
+ function.
+
+ *** Smooth Digital Calibration configuration ***
+ ================================================
+ [..]
+ (+) RTC frequency can be digitally calibrated with a resolution of about
+ 0.954 ppm with a range from -487.1 ppm to +488.5 ppm.
+ The correction of the frequency is performed using a series of small
+ adjustments (adding and/or subtracting individual RTCCLK pulses).
+ (+) The smooth digital calibration is performed during a cycle of about 2^20
+ RTCCLK pulses (or 32 seconds) when the input frequency is 32,768 Hz.
+ This cycle is maintained by a 20-bit counter clocked by RTCCLK.
+ (+) The smooth calibration register (RTC_CALR) specifies the number of RTCCLK
+ clock cycles to be masked during the 32-second cycle.
+ (+) To configure the RTC Smooth Digital Calibration value and the corresponding
+ calibration cycle period (32s,16s and 8s) use the HAL_RTCEx_SetSmoothCalib()
+ function.
+
+ *** Outputs configuration ***
+ =============================
+ [..] The RTC has 2 different outputs:
+ (+) RTC_ALARM: this output is used to manage the RTC alarms (Alarm A and Alarm B)
+ and WaKeUp signals.
+ To output the selected RTC signal, use the HAL_RTC_Init() function.
+ (+) RTC_CALIB: this output is 512Hz signal or 1Hz.
+ To enable the RTC_CALIB, use the HAL_RTCEx_SetCalibrationOutPut() function.
+ (+) Two pins can be used as RTC_ALARM or RTC_CALIB output, selected through
+ bit OUT_RMP of the RTC_OR register:
+ (+) When the RTC_CALIB or RTC_ALARM output is selected, the RTC_OUT pin is
+ automatically configured in output alternate function.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RTCEx RTCEx
+ * @brief RTC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions
+ * @{
+ */
+
+/** @defgroup RTCEx_Exported_Functions_Group1 RTC Timestamp and Tamper functions
+ * @brief RTC Timestamp and Tamper functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Timestamp and Tamper functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Timestamp feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets Timestamp.
+ * @note This API must be called before enabling the Timestamp feature.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param RTC_TimeStampEdge Specifies the pin edge on which the Timestamp is
+ * activated.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPEDGE_RISING: the Timestamp event occurs on
+ * the rising edge of the related pin.
+ * @arg RTC_TIMESTAMPEDGE_FALLING: the Timestamp event occurs on
+ * the falling edge of the related pin.
+ * @param RTC_TimeStampPin Specifies the RTC Timestamp Pin.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC Timestamp Pin.
+ * @note Although unused, parameter RTC_TimeStampPin has been kept for portability
+ * reasons.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t RTC_TimeStampEdge, uint32_t RTC_TimeStampPin)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_TIMESTAMP_EDGE(RTC_TimeStampEdge));
+ assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin));
+
+ /* Prevent compilation warning due to unused argument(s) if assert_param check
+ is disabled */
+ UNUSED(RTC_TimeStampPin);
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ /* Change RTC state to BUSY */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ /* Configure the Timestamp TSEDGE bit */
+ tmpreg |= RTC_TimeStampEdge;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Copy the desired configuration into the CR register */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ /* Clear RTC Timestamp flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+
+ /* Clear RTC Timestamp overrun Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF);
+
+ /* Enable the Timestamp saving */
+ __HAL_RTC_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state back to READY */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets Timestamp with Interrupt.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note This API must be called before enabling the Timestamp feature.
+ * @param RTC_TimeStampEdge Specifies the pin edge on which the Timestamp is
+ * activated.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPEDGE_RISING: the Timestamp event occurs on
+ * the rising edge of the related pin.
+ * @arg RTC_TIMESTAMPEDGE_FALLING: the Timestamp event occurs on
+ * the falling edge of the related pin.
+ * @param RTC_TimeStampPin Specifies the RTC Timestamp Pin.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC Timestamp Pin.
+ * @note Although unused, parameter RTC_TimeStampPin has been kept for portability
+ * reasons.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t RTC_TimeStampEdge, uint32_t RTC_TimeStampPin)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_TIMESTAMP_EDGE(RTC_TimeStampEdge));
+ assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin));
+
+ /* Prevent compilation warning due to unused argument(s) if assert_param check
+ is disabled */
+ UNUSED(RTC_TimeStampPin);
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ /* Change RTC state to BUSY */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ /* Configure the Timestamp TSEDGE bit */
+ tmpreg |= RTC_TimeStampEdge;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Copy the desired configuration into the CR register */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ /* Clear RTC Timestamp flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+
+ /* Clear RTC Timestamp overrun Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF);
+
+ /* Enable the Timestamp saving */
+ __HAL_RTC_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable IT Timestamp */
+ __HAL_RTC_TIMESTAMP_ENABLE_IT(hrtc, RTC_IT_TS);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Enable and configure the EXTI line associated to the RTC Timestamp and Tamper interrupts */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ /* Change RTC state back to READY */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates Timestamp.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* In case interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_TIMESTAMP_DISABLE_IT(hrtc, RTC_IT_TS);
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ /* Configure the Timestamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets Internal Timestamp.
+ * @note This API must be called before enabling the internal Timestamp feature.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Clear the internal Timestamp flag */
+ __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_ITSF);
+
+ /* Configure the internal Timestamp Enable bits */
+ __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates internal Timestamp.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the internal Timestamp Enable bits */
+ __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets the RTC Timestamp value.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTimeStamp Pointer to Time structure
+ * @param sTimeStampDate Pointer to Date structure
+ * @param Format specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format)
+{
+ uint32_t tmptime = 0U;
+ uint32_t tmpdate = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get the Timestamp time and date registers values */
+ tmptime = (uint32_t)(hrtc->Instance->TSTR & RTC_TR_RESERVED_MASK);
+ tmpdate = (uint32_t)(hrtc->Instance->TSDR & RTC_DR_RESERVED_MASK);
+
+ /* Fill the Time structure fields with the read parameters */
+ sTimeStamp->Hours = (uint8_t)((tmptime & (RTC_TSTR_HT | RTC_TSTR_HU)) >> RTC_TSTR_HU_Pos);
+ sTimeStamp->Minutes = (uint8_t)((tmptime & (RTC_TSTR_MNT | RTC_TSTR_MNU)) >> RTC_TSTR_MNU_Pos);
+ sTimeStamp->Seconds = (uint8_t)((tmptime & (RTC_TSTR_ST | RTC_TSTR_SU)) >> RTC_TSTR_SU_Pos);
+ sTimeStamp->TimeFormat = (uint8_t)((tmptime & (RTC_TSTR_PM)) >> RTC_TSTR_PM_Pos);
+ sTimeStamp->SubSeconds = (uint32_t) hrtc->Instance->TSSSR;
+
+ /* Fill the Date structure fields with the read parameters */
+ sTimeStampDate->Year = 0U;
+ sTimeStampDate->Month = (uint8_t)((tmpdate & (RTC_TSDR_MT | RTC_TSDR_MU)) >> RTC_TSDR_MU_Pos);
+ sTimeStampDate->Date = (uint8_t)((tmpdate & (RTC_TSDR_DT | RTC_TSDR_DU)) >> RTC_TSDR_DU_Pos);
+ sTimeStampDate->WeekDay = (uint8_t)((tmpdate & (RTC_TSDR_WDU)) >> RTC_TSDR_WDU_Pos);
+
+ /* Check the input parameters format */
+ if (Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the Timestamp structure parameters to Binary format */
+ sTimeStamp->Hours = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Hours);
+ sTimeStamp->Minutes = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Minutes);
+ sTimeStamp->Seconds = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Seconds);
+
+ /* Convert the DateTimeStamp structure parameters to Binary format */
+ sTimeStampDate->Month = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Month);
+ sTimeStampDate->Date = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Date);
+ sTimeStampDate->WeekDay = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->WeekDay);
+ }
+
+ /* Clear the internal Timestamp Flag */
+ __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_ITSF);
+
+ /* Clear the Timestamp Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets Tamper.
+ * @note By calling this API the tamper global interrupt will be disabled and
+ * the selected tamper's interrupt as well.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTamper Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Copy control register into temporary variable */
+ tmpreg = hrtc->Instance->TAMPCR;
+
+ /* Enable selected tamper */
+ tmpreg |= (sTamper->Tamper);
+
+ /* Configure the tamper trigger bit (this bit is just on the right of the
+ tamper enable bit, hence the one-time right shift before updating it) */
+ if (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE)
+ {
+ /* Set the tamper trigger bit (case of falling edge or high level) */
+ tmpreg |= (uint32_t)(sTamper->Tamper << 1U);
+ }
+ else
+ {
+ /* Clear the tamper trigger bit (case of rising edge or low level) */
+ tmpreg &= (uint32_t)~(sTamper->Tamper << 1U);
+ }
+
+ /* Configure the backup registers erasure enabling bits */
+ if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+ else
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ /* Configure the tamper flags masking bits */
+ if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2MF);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+ else
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2MF);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ /* Clear remaining fields before setting them */
+ tmpreg &= ~(RTC_TAMPERFILTER_MASK | \
+ RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \
+ RTC_TAMPERPRECHARGEDURATION_MASK | \
+ RTC_TAMPER_PULLUP_MASK | \
+ RTC_TIMESTAMPONTAMPERDETECTION_MASK);
+
+ /* Set remaining parameters of desired configuration into temporary variable */
+ tmpreg |= ((uint32_t)sTamper->Filter | \
+ (uint32_t)sTamper->SamplingFrequency | \
+ (uint32_t)sTamper->PrechargeDuration | \
+ (uint32_t)sTamper->TamperPullUp | \
+ (uint32_t)sTamper->TimeStampOnTamperDetection);
+
+ /* Disable interrupt on selected tamper in case it is enabled */
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~RTC_IT_TAMP1;
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~RTC_IT_TAMP2;
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~RTC_IT_TAMP3;
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ /* Disable tamper global interrupt in case it is enabled */
+ tmpreg &= (uint32_t)~RTC_TAMPCR_TAMPIE;
+
+ /* Copy desired configuration into configuration register */
+ hrtc->Instance->TAMPCR = tmpreg;
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets Tamper with interrupt.
+ * @note By setting the tamper global interrupt bit, interrupts will be
+ * enabled for all tampers.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTamper Pointer to RTC Tamper.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_INTERRUPT(sTamper->Interrupt));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Copy control register into temporary variable */
+ tmpreg = hrtc->Instance->TAMPCR;
+
+ /* Enable selected tamper */
+ tmpreg |= (sTamper->Tamper);
+
+ /* Configure the tamper trigger bit (this bit is just on the right of the
+ tamper enable bit, hence the one-time right shift before updating it) */
+ if (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE)
+ {
+ /* Set the tamper trigger bit (case of falling edge or high level) */
+ tmpreg |= (uint32_t)(sTamper->Tamper << 1U);
+ }
+ else
+ {
+ /* Clear the tamper trigger bit (case of rising edge or low level) */
+ tmpreg &= (uint32_t)~(sTamper->Tamper << 1U);
+ }
+
+ /* Configure the backup registers erasure enabling bits */
+ if (sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+ else
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1NOERASE);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2NOERASE);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3NOERASE);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ /* Configure the tamper flags masking bits */
+ if (sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP2MF);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg |= (uint32_t)(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+ else
+ {
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_1) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP1MF);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((sTamper->Tamper & RTC_TAMPER_2) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP2MF);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((sTamper->Tamper & RTC_TAMPER_3) != 0U)
+ {
+ tmpreg &= (uint32_t)~(RTC_TAMPCR_TAMP3MF);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ /* Clear remaining fields before setting them */
+ tmpreg &= ~(RTC_TAMPERFILTER_MASK | \
+ RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \
+ RTC_TAMPERPRECHARGEDURATION_MASK | \
+ RTC_TAMPER_PULLUP_MASK | \
+ RTC_TIMESTAMPONTAMPERDETECTION_MASK);
+
+ /* Set remaining parameters of desired configuration into temporary variable */
+ tmpreg |= ((uint32_t)sTamper->Filter | \
+ (uint32_t)sTamper->SamplingFrequency | \
+ (uint32_t)sTamper->PrechargeDuration | \
+ (uint32_t)sTamper->TamperPullUp | \
+ (uint32_t)sTamper->TimeStampOnTamperDetection);
+
+ /* Enable interrupt on selected tamper */
+ tmpreg |= (uint32_t)sTamper->Interrupt;
+
+ /* Copy desired configuration into configuration register */
+ hrtc->Instance->TAMPCR = tmpreg;
+
+ /* Enable and configure the EXTI line associated to the RTC Timestamp and Tamper interrupts */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates Tamper.
+ * @note By calling this API the tamper global interrupt will be disabled.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Tamper Selected tamper pin.
+ * This parameter can be any combination of the following values:
+ * @arg RTC_TAMPER_1: Tamper 1 (*)
+ * @arg RTC_TAMPER_2: Tamper 2
+ * @arg RTC_TAMPER_3: Tamper 3 (*)
+ *
+ * (*) value not applicable to all devices.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper)
+{
+ assert_param(IS_RTC_TAMPER(Tamper));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the selected Tamper pin */
+ hrtc->Instance->TAMPCR &= (uint32_t)~Tamper;
+
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((Tamper & RTC_TAMPER_1) != 0U)
+ {
+ /* Disable the Tamper 1 interrupt */
+ hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1);
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((Tamper & RTC_TAMPER_2) != 0U)
+ {
+ /* Disable the Tamper 2 interrupt */
+ hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2);
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((Tamper & RTC_TAMPER_3) != 0U)
+ {
+ /* Disable the Tamper 3 interrupt */
+ hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3);
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles Timestamp and Tamper interrupt request.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Clear the EXTI flag associated to the RTC Timestamp and Tamper interrupts */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
+
+ /* Get the Timestamp interrupt source enable status */
+ if (__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != 0U)
+ {
+ /* Get the pending status of the Timestamp Interrupt */
+ if (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != 0U)
+ {
+ /* Timestamp callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->TimeStampEventCallback(hrtc);
+#else
+ HAL_RTCEx_TimeStampEventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+
+ /* Clear the Timestamp interrupt pending bit after returning from callback
+ as RTC_TSTR and RTC_TSDR registers are cleared when TSF bit is reset */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+ }
+ }
+
+#if defined(RTC_TAMPER1_SUPPORT)
+ /* Get the Tamper 1 interrupt source enable status */
+ if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != 0U)
+ {
+ /* Get the pending status of the Tamper 1 Interrupt */
+ if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != 0U)
+ {
+ /* Clear the Tamper interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
+
+ /* Tamper callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->Tamper1EventCallback(hrtc);
+#else
+ HAL_RTCEx_Tamper1EventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+
+ /* Get the Tamper 2 interrupt source enable status */
+ if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != 0U)
+ {
+ /* Get the pending status of the Tamper 2 Interrupt */
+ if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != 0U)
+ {
+ /* Clear the Tamper interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+
+ /* Tamper callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->Tamper2EventCallback(hrtc);
+#else
+ HAL_RTCEx_Tamper2EventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+ }
+
+#if defined(RTC_TAMPER3_SUPPORT)
+ /* Get the Tamper 3 interrupt source enable status */
+ if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != 0U)
+ {
+ /* Get the pending status of the Tamper 3 Interrupt */
+ if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != 0U)
+ {
+ /* Clear the Tamper interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+
+ /* Tamper callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->Tamper3EventCallback(hrtc);
+#else
+ HAL_RTCEx_Tamper3EventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Timestamp callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_TimeStampEventCallback could be implemented in the user file
+ */
+}
+
+#if defined(RTC_TAMPER1_SUPPORT)
+/**
+ * @brief Tamper 1 callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER1_SUPPORT */
+
+/**
+ * @brief Tamper 2 callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file
+ */
+}
+
+#if defined(RTC_TAMPER3_SUPPORT)
+/**
+ * @brief Tamper 3 callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper3EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER3_SUPPORT */
+
+/**
+ * @brief Handles Timestamp polling request.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+
+ if (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSOVF) != 0U)
+ {
+ /* Clear the Timestamp Overrun Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF);
+
+ /* Change Timestamp state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+#if defined(RTC_TAMPER1_SUPPORT)
+/**
+ * @brief Handles Tamper 1 Polling.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER1_SUPPORT */
+
+/**
+ * @brief Handles Tamper 2 Polling.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+#if defined(RTC_TAMPER3_SUPPORT)
+/**
+ * @brief Handles Tamper 3 Polling.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER3_SUPPORT */
+
+/**
+ * @}
+ */
+
+/** @defgroup RTCEx_Exported_Functions_Group2 RTC Wakeup functions
+ * @brief RTC Wakeup functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Wakeup functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Wakeup feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets wakeup timer.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param WakeUpCounter Wakeup counter
+ * @param WakeUpClock Wakeup clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
+{
+ uint32_t tickstart = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock));
+ assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Check RTC WUTWF flag is reset only when wakeup timer enabled*/
+ if ((hrtc->Instance->CR & RTC_CR_WUTE) != 0U)
+ {
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is reset and if timeout is reached exit */
+ while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Disable the Wakeup timer */
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* Clear the Wakeup flag */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear the Wakeup Timer clock source bits in CR register */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL;
+
+ /* Configure the clock source */
+ hrtc->Instance->CR |= (uint32_t)WakeUpClock;
+
+ /* Configure the Wakeup Timer counter */
+ hrtc->Instance->WUTR = (uint32_t)WakeUpCounter;
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets wakeup timer with interrupt.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param WakeUpCounter Wakeup counter
+ * @param WakeUpClock Wakeup clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
+{
+ __IO uint32_t count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U);
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock));
+ assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Check RTC WUTWF flag is reset only when wakeup timer enabled */
+ if ((hrtc->Instance->CR & RTC_CR_WUTE) != 0U)
+ {
+ /* Wait till RTC WUTWF flag is reset and if timeout is reached exit */
+ do
+ {
+ count = count - 1U;
+ if (count == 0U)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ } while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) != 0U);
+ }
+
+ /* Disable the Wakeup timer */
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* Clear the Wakeup flag */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* Reload the counter */
+ count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U);
+
+ /* Wait till RTC WUTWF flag is set and if timeout is reached exit */
+ do
+ {
+ count = count - 1U;
+ if (count == 0U)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ } while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U);
+
+ /* Clear the Wakeup Timer clock source bits in CR register */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL;
+
+ /* Configure the clock source */
+ hrtc->Instance->CR |= (uint32_t)WakeUpClock;
+
+ /* Configure the Wakeup Timer counter */
+ hrtc->Instance->WUTR = (uint32_t)WakeUpCounter;
+
+ /* Enable and configure the EXTI line associated to the RTC Wakeup Timer interrupt */
+ __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
+ __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
+
+ /* Configure the interrupt in the RTC_CR register */
+ __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc, RTC_IT_WUT);
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates wakeup timer counter.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart = 0U;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Disable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* In case interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_WAKEUPTIMER_DISABLE_IT(hrtc, RTC_IT_WUT);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets wakeup timer counter.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval Counter value
+ */
+uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ /* Get the counter value */
+ return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT));
+}
+
+/**
+ * @brief Handles Wakeup Timer interrupt request.
+ * @note Unlike alarm interrupt line (shared by Alarms A and B) or tamper
+ * interrupt line (shared by timestamp and tampers) wakeup timer
+ * interrupt line is exclusive to the wakeup timer.
+ * There is no need in this case to check on the interrupt enable
+ * status via __HAL_RTC_WAKEUPTIMER_GET_IT_SOURCE().
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Clear the EXTI flag associated to the RTC Wakeup Timer interrupt */
+ __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
+
+ /* Get the pending status of the Wakeup timer Interrupt */
+ if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) != 0U)
+ {
+ /* Clear the Wakeup timer interrupt pending bit */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* Wakeup timer callback */
+#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
+ hrtc->WakeUpTimerEventCallback(hrtc);
+#else
+ HAL_RTCEx_WakeUpTimerEventCallback(hrtc);
+#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
+ }
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Wakeup Timer callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handles Wakeup Timer Polling.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Wakeup timer Flag */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Write a data in a specified RTC Backup data register
+ (+) Read a data in a specified RTC Backup data register
+ (+) Set the Smooth calibration parameters.
+ (+) Configure the Synchronization Shift Control Settings.
+ (+) Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ (+) Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ (+) Enable the RTC reference clock detection.
+ (+) Disable the RTC reference clock detection.
+ (+) Enable the Bypass Shadow feature.
+ (+) Disable the Bypass Shadow feature.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Writes a data in a specified RTC Backup data register.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param BackupRegister RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx (where x can be from 0 to 19)
+ * to specify the register.
+ * @param Data Data to be written in the specified RTC Backup data register.
+ * @retval None
+ */
+void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
+{
+ uint32_t tmp = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_BKP(BackupRegister));
+
+ tmp = (uint32_t) &(hrtc->Instance->BKP0R);
+ tmp += (BackupRegister * 4U);
+
+ /* Write the specified register */
+ *(__IO uint32_t *)tmp = (uint32_t)Data;
+}
+
+/**
+ * @brief Reads data from the specified RTC Backup data Register.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param BackupRegister RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx (where x can be from 0 to 19)
+ * to specify the register.
+ * @retval Read value
+ */
+uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
+{
+ uint32_t tmp = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_BKP(BackupRegister));
+
+ tmp = (uint32_t) &(hrtc->Instance->BKP0R);
+ tmp += (BackupRegister * 4U);
+
+ /* Read the specified register */
+ return (*(__IO uint32_t *)tmp);
+}
+
+/**
+ * @brief Sets the Smooth calibration parameters.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param SmoothCalibPeriod Select the Smooth Calibration Period.
+ * This parameter can be can be one of the following values:
+ * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s.
+ * @param SmoothCalibPlusPulses Select to Set or reset the CALP bit.
+ * This parameter can be one of the following values:
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulse every 2*11 pulses.
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added.
+ * @param SmoothCalibMinusPulsesValue Select the value of CALM[8:0] bits.
+ * This parameter can be one any value from 0 to 0x000001FF.
+ * @note To deactivate the smooth calibration, the field SmoothCalibPlusPulses
+ * must be equal to SMOOTHCALIB_PLUSPULSES_RESET and the field
+ * SmoothCalibMinusPulsesValue must be equal to 0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue)
+{
+ uint32_t tickstart = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(SmoothCalibPeriod));
+ assert_param(IS_RTC_SMOOTH_CALIB_PLUS(SmoothCalibPlusPulses));
+ assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmoothCalibMinusPulsesValue));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* check if a calibration is pending*/
+ if ((hrtc->Instance->ISR & RTC_ISR_RECALPF) != 0U)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* check if a calibration is pending*/
+ while ((hrtc->Instance->ISR & RTC_ISR_RECALPF) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Configure the Smooth calibration settings */
+ hrtc->Instance->CALR = (uint32_t)((uint32_t)SmoothCalibPeriod | \
+ (uint32_t)SmoothCalibPlusPulses | \
+ (uint32_t)SmoothCalibMinusPulsesValue);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the Synchronization Shift Control Settings.
+ * @note When REFCKON is set, firmware must not write to Shift control register.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param ShiftAdd1S Select to add or not 1 second to the time calendar.
+ * This parameter can be one of the following values:
+ * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar.
+ * @arg RTC_SHIFTADD1S_RESET: No effect.
+ * @param ShiftSubFS Select the number of Second Fractions to substitute.
+ * This parameter can be one any value from 0 to 0x7FFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef *hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS)
+{
+ uint32_t tickstart = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SHIFT_ADD1S(ShiftAdd1S));
+ assert_param(IS_RTC_SHIFT_SUBFS(ShiftSubFS));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until the shift is completed */
+ while ((hrtc->Instance->ISR & RTC_ISR_SHPF) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check if the reference clock detection is disabled */
+ if ((hrtc->Instance->CR & RTC_CR_REFCKON) == 0U)
+ {
+ /* Configure the Shift settings */
+ hrtc->Instance->SHIFTR = (uint32_t)(uint32_t)(ShiftSubFS) | (uint32_t)(ShiftAdd1S);
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if ((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U)
+ {
+ if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param CalibOutput Select the Calibration output Selection.
+ * This parameter can be one of the following values:
+ * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz.
+ * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef *hrtc, uint32_t CalibOutput)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Clear flags before config */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL;
+
+ /* Configure the RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)CalibOutput;
+
+ __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables the RTC reference clock detection.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Enter Initialization mode */
+ status = RTC_EnterInitMode(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Enable the reference clock detection */
+ __HAL_RTC_CLOCKREF_DETECTION_ENABLE(hrtc);
+
+ /* Exit Initialization mode */
+ status = RTC_ExitInitMode(hrtc);
+ }
+
+ if (status == HAL_OK)
+ {
+ hrtc->State = HAL_RTC_STATE_READY;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+/**
+ * @brief Disable the RTC reference clock detection.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef *hrtc)
+{
+ HAL_StatusTypeDef status;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Enter Initialization mode */
+ status = RTC_EnterInitMode(hrtc);
+
+ if (status == HAL_OK)
+ {
+ /* Disable the reference clock detection */
+ __HAL_RTC_CLOCKREF_DETECTION_DISABLE(hrtc);
+
+ /* Exit Initialization mode */
+ status = RTC_ExitInitMode(hrtc);
+ }
+
+ if (status == HAL_OK)
+ {
+ hrtc->State = HAL_RTC_STATE_READY;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return status;
+}
+
+/**
+ * @brief Enables the Bypass Shadow feature.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set the BYPSHAD bit */
+ hrtc->Instance->CR |= (uint32_t)RTC_CR_BYPSHAD;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables the Bypass Shadow feature.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Reset the BYPSHAD bit */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_BYPSHAD;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTCEx_Exported_Functions_Group4 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) RTC Alarm B callback
+ (+) RTC Poll for Alarm B request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Alarm B callback.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_AlarmBEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handles Alarm B Polling request.
+ * @param hrtc pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0U;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRBF flag is set and if timeout is reached exit */
+ while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) == 0U)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Alarm flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RTC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi.c
new file mode 100644
index 0000000..b29694c
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi.c
@@ -0,0 +1,4481 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_spi.c
+ * @author MCD Application Team
+ * @brief SPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Serial Peripheral Interface (SPI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The SPI HAL driver can be used as follows:
+
+ (#) Declare a SPI_HandleTypeDef handle structure, for example:
+ SPI_HandleTypeDef hspi;
+
+ (#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API:
+ (##) Enable the SPIx interface clock
+ (##) SPI pins configuration
+ (+++) Enable the clock for the SPI GPIOs
+ (+++) Configure these SPI pins as alternate function push-pull
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the SPIx interrupt priority
+ (+++) Enable the NVIC SPI IRQ handle
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel
+ (+++) Enable the DMAx clock
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx Stream/Channel
+ (+++) Associate the initialized hdma_tx(or _rx) handle to the hspi DMA Tx or Rx handle
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx
+ or Rx Stream/Channel
+
+ (#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS
+ management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure.
+
+ (#) Initialize the SPI registers by calling the HAL_SPI_Init() API:
+ (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized HAL_SPI_MspInit() API.
+ [..]
+ Circular mode restriction:
+ (#) The DMA circular mode cannot be used when the SPI is configured in these modes:
+ (##) Master 2Lines RxOnly
+ (##) Master 1Line Rx
+ (#) The CRC feature is not managed when the DMA circular mode is enabled
+ (#) When the SPI DMA Pause/Stop features are used, we must use the following APIs
+ the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks
+ [..]
+ Master Receive mode restriction:
+ (#) In Master unidirectional receive-only mode (MSTR =1, BIDIMODE=0, RXONLY=1) or
+ bidirectional receive mode (MSTR=1, BIDIMODE=1, BIDIOE=0), to ensure that the SPI
+ does not initiate a new transfer the following procedure has to be respected:
+ (##) HAL_SPI_DeInit()
+ (##) HAL_SPI_Init()
+ [..]
+ Callback registration:
+
+ (#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1U
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback.
+
+ Function HAL_SPI_RegisterCallback() allows to register following callbacks:
+ (++) TxCpltCallback : SPI Tx Completed callback
+ (++) RxCpltCallback : SPI Rx Completed callback
+ (++) TxRxCpltCallback : SPI TxRx Completed callback
+ (++) TxHalfCpltCallback : SPI Tx Half Completed callback
+ (++) RxHalfCpltCallback : SPI Rx Half Completed callback
+ (++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
+ (++) ErrorCallback : SPI Error callback
+ (++) AbortCpltCallback : SPI Abort callback
+ (++) MspInitCallback : SPI Msp Init callback
+ (++) MspDeInitCallback : SPI Msp DeInit callback
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+
+ (#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default
+ weak function.
+ HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (++) TxCpltCallback : SPI Tx Completed callback
+ (++) RxCpltCallback : SPI Rx Completed callback
+ (++) TxRxCpltCallback : SPI TxRx Completed callback
+ (++) TxHalfCpltCallback : SPI Tx Half Completed callback
+ (++) RxHalfCpltCallback : SPI Rx Half Completed callback
+ (++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
+ (++) ErrorCallback : SPI Error callback
+ (++) AbortCpltCallback : SPI Abort callback
+ (++) MspInitCallback : SPI Msp Init callback
+ (++) MspDeInitCallback : SPI Msp DeInit callback
+
+ [..]
+ By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+ [..]
+ Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state,
+ thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
+ Then, the user first registers the MspInit/MspDeInit user callbacks
+ using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit()
+ or HAL_SPI_Init() function.
+
+ [..]
+ When the compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (surcharged) callbacks are used.
+
+ [..]
+ Using the HAL it is not possible to reach all supported SPI frequency with the different SPI Modes,
+ the following table resume the max SPI frequency reached with data size 8bits/16bits,
+ according to frequency of the APBx Peripheral Clock (fPCLK) used by the SPI instance.
+
+ @endverbatim
+
+ Additional table :
+
+ DataSize = SPI_DATASIZE_8BIT:
+ +----------------------------------------------------------------------------------------------+
+ | | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |
+ | Process | Transfer mode |---------------------|----------------------|----------------------|
+ | | | Master | Slave | Master | Slave | Master | Slave |
+ |==============================================================================================|
+ | T | Polling | Fpclk/4 | Fpclk/8 | NA | NA | NA | NA |
+ | X |----------------|----------|----------|-----------|----------|-----------|----------|
+ | / | Interrupt | Fpclk/4 | Fpclk/16 | NA | NA | NA | NA |
+ | R |----------------|----------|----------|-----------|----------|-----------|----------|
+ | X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
+ |=========|================|==========|==========|===========|==========|===========|==========|
+ | | Polling | Fpclk/4 | Fpclk/8 | Fpclk/16 | Fpclk/8 | Fpclk/8 | Fpclk/8 |
+ | |----------------|----------|----------|-----------|----------|-----------|----------|
+ | R | Interrupt | Fpclk/8 | Fpclk/16 | Fpclk/8 | Fpclk/8 | Fpclk/8 | Fpclk/4 |
+ | X |----------------|----------|----------|-----------|----------|-----------|----------|
+ | | DMA | Fpclk/4 | Fpclk/2 | Fpclk/2 | Fpclk/16 | Fpclk/2 | Fpclk/16 |
+ |=========|================|==========|==========|===========|==========|===========|==========|
+ | | Polling | Fpclk/8 | Fpclk/2 | NA | NA | Fpclk/8 | Fpclk/8 |
+ | |----------------|----------|----------|-----------|----------|-----------|----------|
+ | T | Interrupt | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/16 | Fpclk/8 |
+ | X |----------------|----------|----------|-----------|----------|-----------|----------|
+ | | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/8 | Fpclk/16 |
+ +----------------------------------------------------------------------------------------------+
+
+ DataSize = SPI_DATASIZE_16BIT:
+ +----------------------------------------------------------------------------------------------+
+ | | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |
+ | Process | Transfer mode |---------------------|----------------------|----------------------|
+ | | | Master | Slave | Master | Slave | Master | Slave |
+ |==============================================================================================|
+ | T | Polling | Fpclk/4 | Fpclk/8 | NA | NA | NA | NA |
+ | X |----------------|----------|----------|-----------|----------|-----------|----------|
+ | / | Interrupt | Fpclk/4 | Fpclk/16 | NA | NA | NA | NA |
+ | R |----------------|----------|----------|-----------|----------|-----------|----------|
+ | X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
+ |=========|================|==========|==========|===========|==========|===========|==========|
+ | | Polling | Fpclk/4 | Fpclk/8 | Fpclk/16 | Fpclk/8 | Fpclk/8 | Fpclk/8 |
+ | |----------------|----------|----------|-----------|----------|-----------|----------|
+ | R | Interrupt | Fpclk/8 | Fpclk/16 | Fpclk/8 | Fpclk/8 | Fpclk/8 | Fpclk/4 |
+ | X |----------------|----------|----------|-----------|----------|-----------|----------|
+ | | DMA | Fpclk/4 | Fpclk/2 | Fpclk/2 | Fpclk/16 | Fpclk/2 | Fpclk/16 |
+ |=========|================|==========|==========|===========|==========|===========|==========|
+ | | Polling | Fpclk/8 | Fpclk/2 | NA | NA | Fpclk/8 | Fpclk/8 |
+ | |----------------|----------|----------|-----------|----------|-----------|----------|
+ | T | Interrupt | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/16 | Fpclk/8 |
+ | X |----------------|----------|----------|-----------|----------|-----------|----------|
+ | | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/8 | Fpclk/16 |
+ +----------------------------------------------------------------------------------------------+
+ @note The max SPI frequency depend on SPI data size (4bits, 5bits,..., 8bits,...15bits, 16bits),
+ SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA).
+ @note
+ (#) TX/RX processes are HAL_SPI_TransmitReceive(), HAL_SPI_TransmitReceive_IT() and
+ HAL_SPI_TransmitReceive_DMA()
+ (#) RX processes are HAL_SPI_Receive(), HAL_SPI_Receive_IT() and HAL_SPI_Receive_DMA()
+ (#) TX processes are HAL_SPI_Transmit(), HAL_SPI_Transmit_IT() and HAL_SPI_Transmit_DMA()
+
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPI SPI
+ * @brief SPI HAL module driver
+ * @{
+ */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPI_Private_Constants SPI Private Constants
+ * @{
+ */
+#define SPI_DEFAULT_TIMEOUT 100U
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup SPI_Private_Functions SPI Private Functions
+ * @{
+ */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAError(DMA_HandleTypeDef *hdma);
+static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
+ uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
+ uint32_t Timeout, uint32_t Tickstart);
+static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+#if (USE_SPI_CRC != 0U)
+static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
+#endif /* USE_SPI_CRC */
+static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi);
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SPI_Exported_Functions SPI Exported Functions
+ * @{
+ */
+
+/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ de-initialize the SPIx peripheral:
+
+ (+) User must implement HAL_SPI_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_SPI_Init() to configure the selected device with
+ the selected configuration:
+ (++) Mode
+ (++) Direction
+ (++) Data Size
+ (++) Clock Polarity and Phase
+ (++) NSS Management
+ (++) BaudRate Prescaler
+ (++) FirstBit
+ (++) TIMode
+ (++) CRC Calculation
+ (++) CRC Polynomial if CRC enabled
+ (++) CRC Length, used only with Data8 and Data16
+ (++) FIFO reception threshold
+
+ (+) Call the function HAL_SPI_DeInit() to restore the default configuration
+ of the selected SPIx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the SPI according to the specified parameters
+ * in the SPI_InitTypeDef and initialize the associated handle.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
+{
+ uint32_t frxth;
+
+ /* Check the SPI handle allocation */
+ if (hspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+ assert_param(IS_SPI_MODE(hspi->Init.Mode));
+ assert_param(IS_SPI_DIRECTION(hspi->Init.Direction));
+ assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize));
+ assert_param(IS_SPI_NSS(hspi->Init.NSS));
+ assert_param(IS_SPI_NSSP(hspi->Init.NSSPMode));
+ assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+ assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit));
+ assert_param(IS_SPI_TIMODE(hspi->Init.TIMode));
+ if (hspi->Init.TIMode == SPI_TIMODE_DISABLE)
+ {
+ assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity));
+ assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase));
+
+ if (hspi->Init.Mode == SPI_MODE_MASTER)
+ {
+ assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+ }
+ else
+ {
+ /* Baudrate prescaler not use in Motoraola Slave mode. force to default value */
+ hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+ }
+ }
+ else
+ {
+ assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+
+ /* Force polarity and phase to TI protocaol requirements */
+ hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
+ }
+#if (USE_SPI_CRC != 0U)
+ assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation));
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
+ assert_param(IS_SPI_CRC_LENGTH(hspi->Init.CRCLength));
+ }
+#else
+ hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+#endif /* USE_SPI_CRC */
+
+ if (hspi->State == HAL_SPI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hspi->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ /* Init the SPI Callback settings */
+ hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
+ hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
+ hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
+ hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+
+ if (hspi->MspInitCallback == NULL)
+ {
+ hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ hspi->MspInitCallback(hspi);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_SPI_MspInit(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY;
+
+ /* Disable the selected SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Align by default the rs fifo threshold on the data size */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ frxth = SPI_RXFIFO_THRESHOLD_HF;
+ }
+ else
+ {
+ frxth = SPI_RXFIFO_THRESHOLD_QF;
+ }
+
+ /* CRC calculation is valid only for 16Bit and 8 Bit */
+ if ((hspi->Init.DataSize != SPI_DATASIZE_16BIT) && (hspi->Init.DataSize != SPI_DATASIZE_8BIT))
+ {
+ /* CRC must be disabled */
+ hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ }
+
+ /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
+ /* Configure : SPI Mode, Communication Mode, Clock polarity and phase, NSS management,
+ Communication speed, First bit and CRC calculation state */
+ WRITE_REG(hspi->Instance->CR1, ((hspi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) |
+ (hspi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) |
+ (hspi->Init.CLKPolarity & SPI_CR1_CPOL) |
+ (hspi->Init.CLKPhase & SPI_CR1_CPHA) |
+ (hspi->Init.NSS & SPI_CR1_SSM) |
+ (hspi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) |
+ (hspi->Init.FirstBit & SPI_CR1_LSBFIRST) |
+ (hspi->Init.CRCCalculation & SPI_CR1_CRCEN)));
+#if (USE_SPI_CRC != 0U)
+ /*---------------------------- SPIx CRCL Configuration -------------------*/
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Align the CRC Length on the data size */
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
+ {
+ /* CRC Length aligned on the data size : value set by default */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
+ }
+ else
+ {
+ hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
+ }
+ }
+
+ /* Configure : CRC Length */
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCL);
+ }
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Configure : NSS management, TI Mode, NSS Pulse, Data size and Rx Fifo threshold */
+ WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) |
+ (hspi->Init.TIMode & SPI_CR2_FRF) |
+ (hspi->Init.NSSPMode & SPI_CR2_NSSP) |
+ (hspi->Init.DataSize & SPI_CR2_DS_Msk) |
+ (frxth & SPI_CR2_FRXTH)));
+
+#if (USE_SPI_CRC != 0U)
+ /*---------------------------- SPIx CRCPOLY Configuration ------------------*/
+ /* Configure : CRC Polynomial */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ WRITE_REG(hspi->Instance->CRCPR, (hspi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk));
+ }
+#endif /* USE_SPI_CRC */
+
+#if defined(SPI_I2SCFGR_I2SMOD)
+ /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
+ CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
+#endif /* SPI_I2SCFGR_I2SMOD */
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->State = HAL_SPI_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief De-Initialize the SPI peripheral.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
+{
+ /* Check the SPI handle allocation */
+ if (hspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check SPI Instance parameter */
+ assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+
+ hspi->State = HAL_SPI_STATE_BUSY;
+
+ /* Disable the SPI Peripheral Clock */
+ __HAL_SPI_DISABLE(hspi);
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ if (hspi->MspDeInitCallback == NULL)
+ {
+ hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ hspi->MspDeInitCallback(hspi);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_SPI_MspDeInit(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->State = HAL_SPI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the SPI MSP.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspInit should be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-Initialize the SPI MSP.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspDeInit should be implemented in the user file
+ */
+}
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+/**
+ * @brief Register a User SPI Callback
+ * To be used instead of the weak predefined callback
+ * @param hspi Pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI.
+ * @param CallbackID ID of the callback to be registered
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID,
+ pSPI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ if (HAL_SPI_STATE_READY == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_TX_COMPLETE_CB_ID :
+ hspi->TxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_RX_COMPLETE_CB_ID :
+ hspi->RxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_TX_RX_COMPLETE_CB_ID :
+ hspi->TxRxCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
+ hspi->TxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
+ hspi->RxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
+ hspi->TxRxHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_ERROR_CB_ID :
+ hspi->ErrorCallback = pCallback;
+ break;
+
+ case HAL_SPI_ABORT_CB_ID :
+ hspi->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SPI_STATE_RESET == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = pCallback;
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspi);
+ return status;
+}
+
+/**
+ * @brief Unregister an SPI Callback
+ * SPI callback is redirected to the weak predefined callback
+ * @param hspi Pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI.
+ * @param CallbackID ID of the callback to be unregistered
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ if (HAL_SPI_STATE_READY == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_TX_COMPLETE_CB_ID :
+ hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
+ break;
+
+ case HAL_SPI_RX_COMPLETE_CB_ID :
+ hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
+ break;
+
+ case HAL_SPI_TX_RX_COMPLETE_CB_ID :
+ hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
+ break;
+
+ case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
+ hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
+ break;
+
+ case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
+ hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
+ break;
+
+ case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
+ hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
+ break;
+
+ case HAL_SPI_ERROR_CB_ID :
+ hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_SPI_ABORT_CB_ID :
+ hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SPI_STATE_RESET == hspi->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SPI_MSPINIT_CB_ID :
+ hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_SPI_MSPDEINIT_CB_ID :
+ hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hspi);
+ return status;
+}
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Exported_Functions_Group2 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SPI
+ data transfers.
+
+ [..] The SPI supports master and slave mode :
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode: The communication is performed using Interrupts
+ or DMA, These APIs return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected
+
+ (#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA)
+ exist for 1Line (simplex) and 2Lines (full duplex) modes.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData pointer to data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be sent
+ * @param Timeout Timeout duration in ms
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint16_t initial_TxXferCount;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+ initial_TxXferCount = Size;
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (const uint8_t *)pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ hspi->RxXferSize = 0U;
+ hspi->RxXferCount = 0U;
+ hspi->TxISR = NULL;
+ hspi->RxISR = NULL;
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+ __HAL_SPI_DISABLE(hspi);
+ SPI_1LINE_TX(hspi);
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Transmit data in 16 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ }
+ /* Transmit data in 16 Bit mode */
+ while (hspi->TxXferCount > 0U)
+ {
+ /* Wait until TXE flag is set to send data */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ /* Transmit data in 8 Bit mode */
+ else
+ {
+ if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+ {
+ if (hspi->TxXferCount > 1U)
+ {
+ /* write on the data register in packing mode */
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2U;
+ }
+ else
+ {
+ *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr ++;
+ hspi->TxXferCount--;
+ }
+ }
+ while (hspi->TxXferCount > 0U)
+ {
+ /* Wait until TXE flag is set to send data */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
+ {
+ if (hspi->TxXferCount > 1U)
+ {
+ /* write on the data register in packing mode */
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2U;
+ }
+ else
+ {
+ *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr++;
+ hspi->TxXferCount--;
+ }
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Clear overrun flag in 2 Lines communication mode because received is not read */
+ if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData pointer to data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be received
+ * @param Timeout Timeout duration in ms
+ * @retval HAL status
+ * @note In master mode, if the direction is set to SPI_DIRECTION_2LINES
+ * the receive buffer is written to data register (DR) to generate
+ * clock pulses and receive data
+ */
+HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+#if (USE_SPI_CRC != 0U)
+ __IO uint32_t tmpreg = 0U;
+ __IO uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+ uint32_t tickstart;
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+ return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
+ }
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->pTxBuffPtr = (uint8_t *)NULL;
+ hspi->TxXferSize = 0U;
+ hspi->TxXferCount = 0U;
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ /* this is done to handle the CRCNEXT before the latest data */
+ hspi->RxXferCount--;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Set the Rx Fifo threshold */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Set RX Fifo threshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* Set RX Fifo threshold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+ /* Configure communication direction: 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+ __HAL_SPI_DISABLE(hspi);
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Receive data in 8 Bit mode */
+ if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+ {
+ /* Transfer loop */
+ while (hspi->RxXferCount > 0U)
+ {
+ /* Check the RXNE flag */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
+ {
+ /* read the received data */
+ (* (uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint8_t);
+ hspi->RxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Transfer loop */
+ while (hspi->RxXferCount > 0U)
+ {
+ /* Check the RXNE flag */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
+ {
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Handle the CRC Transmission */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* freeze the CRC before the latest data */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+
+ /* Read the latest data */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* the latest data has not been received */
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+
+ /* Receive last data in 16 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+ }
+ /* Receive last data in 8 Bit mode */
+ else
+ {
+ (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
+ }
+
+ /* Wait the CRC data */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+
+ /* Read CRC to Flush DR and RXNE flag */
+ if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+ {
+ /* Read 16bit CRC */
+ tmpreg = READ_REG(hspi->Instance->DR);
+ /* To avoid GCC warning */
+ UNUSED(tmpreg);
+ }
+ else
+ {
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+ /* Read 8bit CRC */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+
+ if ((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ {
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+ }
+ }
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Check if CRC error occurred */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Unlock the process */
+ __HAL_UNLOCK(hspi);
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in blocking mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData pointer to transmission data buffer (u8 or u16 data elements)
+ * @param pRxData pointer to reception data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be sent and received
+ * @param Timeout Timeout duration in ms
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint16_t initial_TxXferCount;
+ uint16_t initial_RxXferCount;
+ uint32_t tmp_mode;
+ HAL_SPI_StateTypeDef tmp_state;
+ uint32_t tickstart;
+#if (USE_SPI_CRC != 0U)
+ __IO uint32_t tmpreg = 0U;
+ uint32_t spi_cr1;
+ uint32_t spi_cr2;
+ __IO uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+
+ /* Variable used to alternate Rx and Tx during transfer */
+ uint32_t txallowed = 1U;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* Init temporary variables */
+ tmp_state = hspi->State;
+ tmp_mode = hspi->Init.Mode;
+ initial_TxXferCount = Size;
+ initial_RxXferCount = Size;
+#if (USE_SPI_CRC != 0U)
+ spi_cr1 = READ_REG(hspi->Instance->CR1);
+ spi_cr2 = READ_REG(hspi->Instance->CR2);
+#endif /* USE_SPI_CRC */
+
+ if (!((tmp_state == HAL_SPI_STATE_READY) || \
+ ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
+ (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the transaction information */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferCount = Size;
+ hspi->RxXferSize = Size;
+ hspi->pTxBuffPtr = (const uint8_t *)pTxData;
+ hspi->TxXferCount = Size;
+ hspi->TxXferSize = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Set the Rx Fifo threshold */
+ if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (initial_RxXferCount > 1U))
+ {
+ /* Set fiforxthreshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* Set fiforxthreshold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Transmit and Receive data in 16 Bit mode */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+ if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+ }
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+
+ }
+ while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
+ {
+ /* Check TXE flag */
+ if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ /* Next Data is a reception (Rx). Tx not allowed */
+ txallowed = 0U;
+
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+ if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+ }
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+ }
+
+ /* Check RXNE flag */
+ if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
+ {
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ /* Next Data is a Transmission (Tx). Tx is allowed */
+ txallowed = 1U;
+ }
+ if (((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Transmit and Receive data in 8 Bit mode */
+ else
+ {
+ if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+ {
+ if (hspi->TxXferCount > 1U)
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2U;
+ }
+ else
+ {
+ *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr++;
+ hspi->TxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+ if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+ }
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+ }
+ }
+ while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
+ {
+ /* Check TXE flag */
+ if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
+ {
+ if (hspi->TxXferCount > 1U)
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2U;
+ }
+ else
+ {
+ *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr++;
+ hspi->TxXferCount--;
+ }
+ /* Next Data is a reception (Rx). Tx not allowed */
+ txallowed = 0U;
+
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+ if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+ }
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+ }
+
+ /* Wait until RXNE flag is reset */
+ if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
+ {
+ if (hspi->RxXferCount > 1U)
+ {
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount -= 2U;
+ if (hspi->RxXferCount <= 1U)
+ {
+ /* Set RX Fifo threshold before to switch on 8 bit data size */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ }
+ else
+ {
+ (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
+ hspi->pRxBuffPtr++;
+ hspi->RxXferCount--;
+ }
+ /* Next Data is a Transmission (Tx). Tx is allowed */
+ txallowed = 1U;
+ }
+ if ((((HAL_GetTick() - tickstart) >= Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Read CRC from DR to close CRC calculation process */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Wait until TXE flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ /* Read CRC */
+ if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+ {
+ /* Read 16bit CRC */
+ tmpreg = READ_REG(hspi->Instance->DR);
+ /* To avoid GCC warning */
+ UNUSED(tmpreg);
+ }
+ else
+ {
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+ /* Read 8bit CRC */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ {
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+ }
+ }
+ }
+
+ /* Check if CRC error occurred */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ /* Clear CRC Flag */
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+
+
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Unlock the process */
+ __HAL_UNLOCK(hspi);
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData pointer to data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
+{
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (const uint8_t *)pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ hspi->RxXferSize = 0U;
+ hspi->RxXferCount = 0U;
+ hspi->RxISR = NULL;
+
+ /* Set the function for IT treatment */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->TxISR = SPI_TxISR_16BIT;
+ }
+ else
+ {
+ hspi->TxISR = SPI_TxISR_8BIT;
+ }
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+ __HAL_SPI_DISABLE(hspi);
+ SPI_1LINE_TX(hspi);
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ /* Enable TXE and ERR interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData pointer to data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+ return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size);
+ }
+
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->pTxBuffPtr = (uint8_t *)NULL;
+ hspi->TxXferSize = 0U;
+ hspi->TxXferCount = 0U;
+ hspi->TxISR = NULL;
+
+ /* Check the data size to adapt Rx threshold and the set the function for IT treatment */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Set RX Fifo threshold according the reception data length: 16 bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_RxISR_16BIT;
+ }
+ else
+ {
+ /* Set RX Fifo threshold according the reception data length: 8 bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_RxISR_8BIT;
+ }
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+ __HAL_SPI_DISABLE(hspi);
+ SPI_1LINE_RX(hspi);
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->CRCSize = 1U;
+ if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ {
+ hspi->CRCSize = 2U;
+ }
+ SPI_RESET_CRC(hspi);
+ }
+ else
+ {
+ hspi->CRCSize = 0U;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Note : The SPI must be enabled after unlocking current process
+ to avoid the risk of SPI interrupt handle execution before current
+ process unlock */
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ /* Enable RXNE and ERR interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData pointer to transmission data buffer (u8 or u16 data elements)
+ * @param pRxData pointer to reception data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be sent and received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size)
+{
+ uint32_t tmp_mode;
+ HAL_SPI_StateTypeDef tmp_state;
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Init temporary variables */
+ tmp_state = hspi->State;
+ tmp_mode = hspi->Init.Mode;
+
+ if (!((tmp_state == HAL_SPI_STATE_READY) || \
+ ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
+ (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the transaction information */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (const uint8_t *)pTxData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Set the function for IT treatment */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->RxISR = SPI_2linesRxISR_16BIT;
+ hspi->TxISR = SPI_2linesTxISR_16BIT;
+ }
+ else
+ {
+ hspi->RxISR = SPI_2linesRxISR_8BIT;
+ hspi->TxISR = SPI_2linesTxISR_8BIT;
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->CRCSize = 1U;
+ if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ {
+ hspi->CRCSize = 2U;
+ }
+ SPI_RESET_CRC(hspi);
+ }
+ else
+ {
+ hspi->CRCSize = 0U;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check if packing mode is enabled and if there is more than 2 data to receive */
+ if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (Size >= 2U))
+ {
+ /* Set RX Fifo threshold according the reception data length: 16 bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* Set RX Fifo threshold according the reception data length: 8 bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ /* Enable TXE, RXNE and ERR interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData pointer to data buffer (u8 or u16 data elements)
+ * @param Size amount of data elements (u8 or u16) to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
+{
+
+ /* Check tx dma handle */
+ assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (const uint8_t *)pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ hspi->TxISR = NULL;
+ hspi->RxISR = NULL;
+ hspi->RxXferSize = 0U;
+ hspi->RxXferCount = 0U;
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+ __HAL_SPI_DISABLE(hspi);
+ SPI_1LINE_TX(hspi);
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Set the SPI TxDMA Half transfer complete callback */
+ hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt;
+
+ /* Set the SPI TxDMA transfer complete callback */
+ hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt;
+
+ /* Set the DMA error callback */
+ hspi->hdmatx->XferErrorCallback = SPI_DMAError;
+
+ /* Set the DMA AbortCpltCallback */
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ /* Packing mode is enabled only if the DMA setting is HALWORD */
+ if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD))
+ {
+ /* Check the even/odd of the data size + crc if enabled */
+ if ((hspi->TxXferCount & 0x1U) == 0U)
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = (hspi->TxXferCount >> 1U);
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = (hspi->TxXferCount >> 1U) + 1U;
+ }
+ }
+
+ /* Enable the Tx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
+ hspi->TxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ /* Enable the SPI Error Interrupt Bit */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
+
+ /* Enable Tx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @note In case of MASTER mode and SPI_DIRECTION_2LINES direction, hdmatx shall be defined.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData pointer to data buffer (u8 or u16 data elements)
+ * @note When the CRC feature is enabled the pData Length must be Size + 1.
+ * @param Size amount of data elements (u8 or u16) to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ /* Check rx dma handle */
+ assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
+
+ if (hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+
+ /* Check tx dma handle */
+ assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
+
+ /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+ return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size);
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = (uint8_t *)pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /*Init field not used in handle to zero */
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+ hspi->TxXferSize = 0U;
+ hspi->TxXferCount = 0U;
+
+ /* Configure communication direction : 1Line */
+ if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+ __HAL_SPI_DISABLE(hspi);
+ SPI_1LINE_RX(hspi);
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Set RX Fifo threshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* Set RX Fifo threshold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ /* Set RX Fifo threshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ if ((hspi->RxXferCount & 0x1U) == 0x0U)
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ hspi->RxXferCount = hspi->RxXferCount >> 1U;
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ hspi->RxXferCount = (hspi->RxXferCount >> 1U) + 1U;
+ }
+ }
+ }
+
+ /* Set the SPI RxDMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+
+ /* Set the SPI Rx DMA transfer complete callback */
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Set the DMA AbortCpltCallback */
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the Rx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
+ hspi->RxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ /* Enable the SPI Error Interrupt Bit */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
+
+ /* Enable Rx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in non-blocking mode with DMA.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData pointer to transmission data buffer (u8 or u16 data elements)
+ * @param pRxData pointer to reception data buffer (u8 or u16 data elements)
+ * @note When the CRC feature is enabled the pRxData Length must be Size + 1
+ * @param Size amount of data elements (u8 or u16) to be sent and received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+ uint16_t Size)
+{
+ uint32_t tmp_mode;
+ HAL_SPI_StateTypeDef tmp_state;
+
+ /* Check rx & tx dma handles */
+ assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
+ assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
+
+ /* Check Direction parameter */
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Init temporary variables */
+ tmp_state = hspi->State;
+ tmp_mode = hspi->Init.Mode;
+
+ if (!((tmp_state == HAL_SPI_STATE_READY) ||
+ ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
+ (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+ {
+ return HAL_BUSY;
+ }
+
+ if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+ if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ /* Set the transaction information */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (const uint8_t *)pTxData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Init field not used in handle to zero */
+ hspi->RxISR = NULL;
+ hspi->TxISR = NULL;
+
+#if (USE_SPI_CRC != 0U)
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Reset the threshold bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX | SPI_CR2_LDMARX);
+
+ /* The packing mode management is enabled by the DMA settings according the spi data size */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Set fiforxthreshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* Set RX Fifo threshold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ if ((hspi->TxXferSize & 0x1U) == 0x0U)
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = hspi->TxXferCount >> 1U;
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = (hspi->TxXferCount >> 1U) + 1U;
+ }
+ }
+
+ if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ /* Set RX Fifo threshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ if ((hspi->RxXferCount & 0x1U) == 0x0U)
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ hspi->RxXferCount = hspi->RxXferCount >> 1U;
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ hspi->RxXferCount = (hspi->RxXferCount >> 1U) + 1U;
+ }
+ }
+ }
+
+ /* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
+ if (hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ /* Set the SPI Rx DMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+ }
+ else
+ {
+ /* Set the SPI Tx/Rx DMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
+ }
+
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Set the DMA AbortCpltCallback */
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the Rx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
+ hspi->RxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+
+ /* Enable Rx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
+ is performed in DMA reception complete callback */
+ hspi->hdmatx->XferHalfCpltCallback = NULL;
+ hspi->hdmatx->XferCpltCallback = NULL;
+ hspi->hdmatx->XferErrorCallback = NULL;
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the Tx DMA Stream/Channel */
+ if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
+ hspi->TxXferCount))
+ {
+ /* Update SPI error code */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+
+ /* Check if the SPI is already enabled */
+ if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ /* Enable the SPI Error Interrupt Bit */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
+
+ /* Enable Tx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort ongoing transfer (blocking mode).
+ * @param hspi SPI handle.
+ * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
+ * started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SPI Interrupts (depending of transfer direction)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi)
+{
+ HAL_StatusTypeDef errorcode;
+ __IO uint32_t count;
+ __IO uint32_t resetcount;
+
+ /* Initialized local variable */
+ errorcode = HAL_OK;
+ resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+ count = resetcount;
+
+ /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
+
+ /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
+ {
+ hspi->TxISR = SPI_AbortTx_ISR;
+ /* Wait HAL_SPI_STATE_ABORT state */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (hspi->State != HAL_SPI_STATE_ABORT);
+ /* Reset Timeout Counter */
+ count = resetcount;
+ }
+
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
+ {
+ hspi->RxISR = SPI_AbortRx_ISR;
+ /* Wait HAL_SPI_STATE_ABORT state */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (hspi->State != HAL_SPI_STATE_ABORT);
+ /* Reset Timeout Counter */
+ count = resetcount;
+ }
+
+ /* Disable the SPI DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
+ {
+ /* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */
+ if (hspi->hdmatx != NULL)
+ {
+ /* Set the SPI DMA Abort callback :
+ will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Abort DMA Tx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN));
+
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Disable SPI Peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+ }
+ }
+
+ /* Disable the SPI DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
+ {
+ /* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */
+ if (hspi->hdmarx != NULL)
+ {
+ /* Set the SPI DMA Abort callback :
+ will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Abort DMA Rx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Disable peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Control the BSY flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Disable Rx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXDMAEN));
+ }
+ }
+ /* Reset Tx and Rx transfer counters */
+ hspi->RxXferCount = 0U;
+ hspi->TxXferCount = 0U;
+
+ /* Check error during Abort procedure */
+ if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
+ {
+ /* return HAL_Error in case of error during Abort procedure */
+ errorcode = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset errorCode */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ }
+
+ /* Clear the Error flags in the SR register */
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+ /* Restore hspi->state to ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ return errorcode;
+}
+
+/**
+ * @brief Abort ongoing transfer (Interrupt mode).
+ * @param hspi SPI handle.
+ * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
+ * started in Interrupt or DMA mode.
+ * This procedure performs following operations :
+ * - Disable SPI Interrupts (depending of transfer direction)
+ * - Disable the DMA transfer in the peripheral register (if enabled)
+ * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+ * - Set handle State to READY
+ * - At abort completion, call user abort complete callback
+ * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
+ * considered as completed only when user abort complete callback is executed (not when exiting function).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi)
+{
+ HAL_StatusTypeDef errorcode;
+ uint32_t abortcplt ;
+ __IO uint32_t count;
+ __IO uint32_t resetcount;
+
+ /* Initialized local variable */
+ errorcode = HAL_OK;
+ abortcplt = 1U;
+ resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+ count = resetcount;
+
+ /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
+
+ /* Change Rx and Tx Irq Handler to Disable TXEIE, RXNEIE and ERRIE interrupts */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
+ {
+ hspi->TxISR = SPI_AbortTx_ISR;
+ /* Wait HAL_SPI_STATE_ABORT state */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (hspi->State != HAL_SPI_STATE_ABORT);
+ /* Reset Timeout Counter */
+ count = resetcount;
+ }
+
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
+ {
+ hspi->RxISR = SPI_AbortRx_ISR;
+ /* Wait HAL_SPI_STATE_ABORT state */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (hspi->State != HAL_SPI_STATE_ABORT);
+ /* Reset Timeout Counter */
+ count = resetcount;
+ }
+
+ /* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialised
+ before any call to DMA Abort functions */
+ /* DMA Tx Handle is valid */
+ if (hspi->hdmatx != NULL)
+ {
+ /* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
+ {
+ hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback;
+ }
+ else
+ {
+ hspi->hdmatx->XferAbortCallback = NULL;
+ }
+ }
+ /* DMA Rx Handle is valid */
+ if (hspi->hdmarx != NULL)
+ {
+ /* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
+ Otherwise, set it to NULL */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
+ {
+ hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback;
+ }
+ else
+ {
+ hspi->hdmarx->XferAbortCallback = NULL;
+ }
+ }
+
+ /* Disable the SPI DMA Tx request if enabled */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
+ {
+ /* Abort the SPI DMA Tx Stream/Channel */
+ if (hspi->hdmatx != NULL)
+ {
+ /* Abort DMA Tx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK)
+ {
+ hspi->hdmatx->XferAbortCallback = NULL;
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+ /* Disable the SPI DMA Rx request if enabled */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
+ {
+ /* Abort the SPI DMA Rx Stream/Channel */
+ if (hspi->hdmarx != NULL)
+ {
+ /* Abort DMA Rx Handle linked to SPI Peripheral */
+ if (HAL_DMA_Abort_IT(hspi->hdmarx) != HAL_OK)
+ {
+ hspi->hdmarx->XferAbortCallback = NULL;
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+ else
+ {
+ abortcplt = 0U;
+ }
+ }
+ }
+
+ if (abortcplt == 1U)
+ {
+ /* Reset Tx and Rx transfer counters */
+ hspi->RxXferCount = 0U;
+ hspi->TxXferCount = 0U;
+
+ /* Check error during Abort procedure */
+ if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
+ {
+ /* return HAL_Error in case of error during Abort procedure */
+ errorcode = HAL_ERROR;
+ }
+ else
+ {
+ /* Reset errorCode */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ }
+
+ /* Clear the Error flags in the SR register */
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->AbortCpltCallback(hspi);
+#else
+ HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+
+ return errorcode;
+}
+
+/**
+ * @brief Pause the DMA Transfer.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
+{
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Disable the SPI DMA Tx & Rx requests */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
+{
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Enable the SPI DMA Tx & Rx requests */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
+ HAL_SPI_TxRxCpltCallback():
+ when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
+ and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
+ HAL_SPI_TxRxCpltCallback()
+ */
+
+ /* Abort the SPI DMA tx Stream/Channel */
+ if (hspi->hdmatx != NULL)
+ {
+ if (HAL_OK != HAL_DMA_Abort(hspi->hdmatx))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ }
+ }
+ /* Abort the SPI DMA rx Stream/Channel */
+ if (hspi->hdmarx != NULL)
+ {
+ if (HAL_OK != HAL_DMA_Abort(hspi->hdmarx))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ errorcode = HAL_ERROR;
+ }
+ }
+
+ /* Disable the SPI DMA Tx & Rx requests */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+ hspi->State = HAL_SPI_STATE_READY;
+ return errorcode;
+}
+
+/**
+ * @brief Handle SPI interrupt request.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval None
+ */
+void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
+{
+ uint32_t itsource = hspi->Instance->CR2;
+ uint32_t itflag = hspi->Instance->SR;
+
+ /* SPI in mode Receiver ----------------------------------------------------*/
+ if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) &&
+ (SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET))
+ {
+ hspi->RxISR(hspi);
+ return;
+ }
+
+ /* SPI in mode Transmitter -------------------------------------------------*/
+ if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET))
+ {
+ hspi->TxISR(hspi);
+ return;
+ }
+
+ /* SPI in Error Treatment --------------------------------------------------*/
+ if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
+ || (SPI_CHECK_FLAG(itflag, SPI_FLAG_FRE) != RESET)) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET))
+ {
+ /* SPI Overrun error interrupt occurred ----------------------------------*/
+ if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
+ {
+ if (hspi->State != HAL_SPI_STATE_BUSY_TX)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+ else
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ return;
+ }
+ }
+
+ /* SPI Mode Fault error interrupt occurred -------------------------------*/
+ if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
+ __HAL_SPI_CLEAR_MODFFLAG(hspi);
+ }
+
+ /* SPI Frame error interrupt occurred ------------------------------------*/
+ if (SPI_CHECK_FLAG(itflag, SPI_FLAG_FRE) != RESET)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FRE);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+ }
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ /* Disable all interrupts */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
+
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Disable the SPI DMA requests if enabled */
+ if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN)))
+ {
+ CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN));
+
+ /* Abort the SPI DMA Rx channel */
+ if (hspi->hdmarx != NULL)
+ {
+ /* Set the SPI DMA Abort callback :
+ will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
+ hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError;
+ if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ }
+ }
+ /* Abort the SPI DMA Tx channel */
+ if (hspi->hdmatx != NULL)
+ {
+ /* Set the SPI DMA Abort callback :
+ will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
+ hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError;
+ if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ }
+ }
+ }
+ else
+ {
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ }
+ return;
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_RxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx and Rx Transfer completed callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxRxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxHalfCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx and Rx Half Transfer callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file
+ */
+}
+
+/**
+ * @brief SPI error callback.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_ErrorCallback should be implemented in the user file
+ */
+ /* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes
+ and user can use HAL_SPI_GetError() API to check the latest error occurred
+ */
+}
+
+/**
+ * @brief SPI Abort Complete callback.
+ * @param hspi SPI handle.
+ * @retval None
+ */
+__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_AbortCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief SPI control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SPI.
+ (+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral
+ (+) HAL_SPI_GetError() check in run-time Errors occurring during communication
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the SPI handle state.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval SPI state
+ */
+HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi)
+{
+ /* Return SPI handle state */
+ return hspi->State;
+}
+
+/**
+ * @brief Return the SPI error code.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval SPI error code in bitmap format
+ */
+uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi)
+{
+ /* Return SPI ErrorCode */
+ return hspi->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SPI_Private_Functions
+ * @brief Private functions
+ * @{
+ */
+
+/**
+ * @brief DMA SPI transmit process complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tickstart;
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* DMA Normal Mode */
+ if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+ {
+ /* Disable ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+
+ /* Clear overrun flag in 2 Lines communication mode because received data is not read */
+ if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ hspi->TxXferCount = 0U;
+ hspi->State = HAL_SPI_STATE_READY;
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ return;
+ }
+ }
+ /* Call user Tx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->TxCpltCallback(hspi);
+#else
+ HAL_SPI_TxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI receive process complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tickstart;
+#if (USE_SPI_CRC != 0U)
+ __IO uint32_t tmpreg = 0U;
+ __IO uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* DMA Normal Mode */
+ if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+ {
+ /* Disable ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+#if (USE_SPI_CRC != 0U)
+ /* CRC handling */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Wait until RXNE flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ }
+ /* Read CRC */
+ if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Read 16bit CRC */
+ tmpreg = READ_REG(hspi->Instance->DR);
+ /* To avoid GCC warning */
+ UNUSED(tmpreg);
+ }
+ else
+ {
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+ /* Read 8bit CRC */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+
+ if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ {
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ }
+ /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+ }
+ }
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check if we are in Master RX 2 line mode */
+ if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+ {
+ /* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+ }
+ else
+ {
+ /* Normal case */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+ }
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ hspi->RxXferCount = 0U;
+ hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_SPI_CRC != 0U)
+ /* Check if CRC error occurred */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ return;
+ }
+ }
+ /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->RxCpltCallback(hspi);
+#else
+ HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI transmit receive process complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tickstart;
+#if (USE_SPI_CRC != 0U)
+ __IO uint32_t tmpreg = 0U;
+ __IO uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* DMA Normal Mode */
+ if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+ {
+ /* Disable ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+#if (USE_SPI_CRC != 0U)
+ /* CRC handling */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ if ((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_8BIT))
+ {
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_QUARTER_FULL, SPI_DEFAULT_TIMEOUT,
+ tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ }
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+ /* Read 8bit CRC */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+ }
+ else
+ {
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_HALF_FULL, SPI_DEFAULT_TIMEOUT,
+ tickstart) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ }
+ /* Read CRC to Flush DR and RXNE flag */
+ tmpreg = READ_REG(hspi->Instance->DR);
+ /* To avoid GCC warning */
+ UNUSED(tmpreg);
+ }
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+
+ /* Disable Rx/Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ hspi->TxXferCount = 0U;
+ hspi->RxXferCount = 0U;
+ hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_SPI_CRC != 0U)
+ /* Check if CRC error occurred */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+#endif /* USE_SPI_CRC */
+
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ return;
+ }
+ }
+ /* Call user TxRx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->TxRxCpltCallback(hspi);
+#else
+ HAL_SPI_TxRxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI half transmit process complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Call user Tx half complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->TxHalfCpltCallback(hspi);
+#else
+ HAL_SPI_TxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI half receive process complete callback
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Call user Rx half complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->RxHalfCpltCallback(hspi);
+#else
+ HAL_SPI_RxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI half transmit receive process complete callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Call user TxRx half complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->TxRxHalfCpltCallback(hspi);
+#else
+ HAL_SPI_TxRxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI communication error callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Stop the disable DMA transfer on SPI side */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI communication abort callback, when initiated by HAL services on Error
+ * (To be called at end of DMA Abort procedure following error occurrence).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ hspi->RxXferCount = 0U;
+ hspi->TxXferCount = 0U;
+
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI Tx communication abort callback, when initiated by user
+ * (To be called at end of DMA Tx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Rx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ hspi->hdmatx->XferAbortCallback = NULL;
+
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Disable SPI Peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Check if an Abort process is still ongoing */
+ if (hspi->hdmarx != NULL)
+ {
+ if (hspi->hdmarx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
+ hspi->RxXferCount = 0U;
+ hspi->TxXferCount = 0U;
+
+ /* Check no error during Abort procedure */
+ if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
+ {
+ /* Reset errorCode */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ }
+
+ /* Clear the Error flags in the SR register */
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->AbortCpltCallback(hspi);
+#else
+ HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief DMA SPI Rx communication abort callback, when initiated by user
+ * (To be called at end of DMA Rx Abort procedure following user abort request).
+ * @note When this callback is executed, User Abort complete call back is called only if no
+ * Abort still ongoing for Tx DMA Handle.
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Disable SPI Peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ hspi->hdmarx->XferAbortCallback = NULL;
+
+ /* Disable Rx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ /* Control the BSY flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Check if an Abort process is still ongoing */
+ if (hspi->hdmatx != NULL)
+ {
+ if (hspi->hdmatx->XferAbortCallback != NULL)
+ {
+ return;
+ }
+ }
+
+ /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
+ hspi->RxXferCount = 0U;
+ hspi->TxXferCount = 0U;
+
+ /* Check no error during Abort procedure */
+ if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
+ {
+ /* Reset errorCode */
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ }
+
+ /* Clear the Error flags in the SR register */
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+ /* Restore hspi->State to Ready */
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->AbortCpltCallback(hspi);
+#else
+ HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in packing mode */
+ if (hspi->RxXferCount > 1U)
+ {
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount -= 2U;
+ if (hspi->RxXferCount == 1U)
+ {
+ /* Set RX Fifo threshold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ }
+ /* Receive data in 8 Bit mode */
+ else
+ {
+ *hspi->pRxBuffPtr = *((__IO uint8_t *)&hspi->Instance->DR);
+ hspi->pRxBuffPtr++;
+ hspi->RxXferCount--;
+ }
+
+ /* Check end of the reception */
+ if (hspi->RxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_2linesRxISR_8BITCRC;
+ return;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Disable RXNE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ if (hspi->TxXferCount == 0U)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+ * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+ /* Read 8bit CRC to flush Data Register */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+
+ hspi->CRCSize--;
+
+ /* Check end of the reception */
+ if (hspi->CRCSize == 0U)
+ {
+ /* Disable RXNE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ if (hspi->TxXferCount == 0U)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+#endif /* USE_SPI_CRC */
+
+/**
+ * @brief Tx 8-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in packing Bit mode */
+ if (hspi->TxXferCount >= 2U)
+ {
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2U;
+ }
+ /* Transmit data in 8 Bit mode */
+ else
+ {
+ *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr++;
+ hspi->TxXferCount--;
+ }
+
+ /* Check the end of the transmission */
+ if (hspi->TxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Set CRC Next Bit to send CRC */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ /* Disable TXE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+ return;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Disable TXE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+
+ if (hspi->RxXferCount == 0U)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Rx 16-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in 16 Bit mode */
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+
+ if (hspi->RxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->RxISR = SPI_2linesRxISR_16BITCRC;
+ return;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Disable RXNE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+ if (hspi->TxXferCount == 0U)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+ * @brief Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint32_t tmpreg = 0U;
+
+ /* Read 16bit CRC to flush Data Register */
+ tmpreg = READ_REG(hspi->Instance->DR);
+ /* To avoid GCC warning */
+ UNUSED(tmpreg);
+
+ /* Disable RXNE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+ SPI_CloseRxTx_ISR(hspi);
+}
+#endif /* USE_SPI_CRC */
+
+/**
+ * @brief Tx 16-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 16 Bit mode */
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+ /* Enable CRC Transmission */
+ if (hspi->TxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Set CRC Next Bit to send CRC */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ /* Disable TXE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+ return;
+ }
+#endif /* USE_SPI_CRC */
+
+ /* Disable TXE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+
+ if (hspi->RxXferCount == 0U)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+ * @brief Manage the CRC 8-bit receive in Interrupt context.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+ /* Read 8bit CRC to flush Data Register */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+
+ hspi->CRCSize--;
+
+ if (hspi->CRCSize == 0U)
+ {
+ SPI_CloseRx_ISR(hspi);
+ }
+}
+#endif /* USE_SPI_CRC */
+
+/**
+ * @brief Manage the receive 8-bit in Interrupt context.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ *hspi->pRxBuffPtr = (*(__IO uint8_t *)&hspi->Instance->DR);
+ hspi->pRxBuffPtr++;
+ hspi->RxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+
+ if (hspi->RxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->RxISR = SPI_RxISR_8BITCRC;
+ return;
+ }
+#endif /* USE_SPI_CRC */
+ SPI_CloseRx_ISR(hspi);
+ }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+ * @brief Manage the CRC 16-bit receive in Interrupt context.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint32_t tmpreg = 0U;
+
+ /* Read 16bit CRC to flush Data Register */
+ tmpreg = READ_REG(hspi->Instance->DR);
+ /* To avoid GCC warning */
+ UNUSED(tmpreg);
+
+ /* Disable RXNE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ SPI_CloseRx_ISR(hspi);
+}
+#endif /* USE_SPI_CRC */
+
+/**
+ * @brief Manage the 16-bit receive in Interrupt context.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+ /* Enable CRC Transmission */
+ if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+
+ if (hspi->RxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->RxISR = SPI_RxISR_16BITCRC;
+ return;
+ }
+#endif /* USE_SPI_CRC */
+ SPI_CloseRx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Handle the data 8-bit transmit in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr++;
+ hspi->TxXferCount--;
+
+ if (hspi->TxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Enable CRC Transmission */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+ SPI_CloseTx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Handle the data 16-bit transmit in Interrupt mode.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 16 Bit mode */
+ hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+ if (hspi->TxXferCount == 0U)
+ {
+#if (USE_SPI_CRC != 0U)
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Enable CRC Transmission */
+ SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+ }
+#endif /* USE_SPI_CRC */
+ SPI_CloseTx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Handle SPI Communication Timeout.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Flag SPI flag to check
+ * @param State flag state to check
+ * @param Timeout Timeout duration
+ * @param Tickstart tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
+ uint32_t Timeout, uint32_t Tickstart)
+{
+ __IO uint32_t count;
+ uint32_t tmp_timeout;
+ uint32_t tmp_tickstart;
+
+ /* Adjust Timeout value in case of end of transfer */
+ tmp_timeout = Timeout - (HAL_GetTick() - Tickstart);
+ tmp_tickstart = HAL_GetTick();
+
+ /* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */
+ count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U);
+
+ while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
+ {
+ /* Disable the SPI and reset the CRC: the CRC value should be cleared
+ on both master and slave sides in order to resynchronize the master
+ and slave for their respective CRC calculation */
+
+ /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_TIMEOUT;
+ }
+ /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
+ if (count == 0U)
+ {
+ tmp_timeout = 0U;
+ }
+ else
+ {
+ count--;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle SPI FIFO Communication Timeout.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Fifo Fifo to check
+ * @param State Fifo state to check
+ * @param Timeout Timeout duration
+ * @param Tickstart tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
+ uint32_t Timeout, uint32_t Tickstart)
+{
+ __IO uint32_t count;
+ uint32_t tmp_timeout;
+ uint32_t tmp_tickstart;
+ __IO const uint8_t *ptmpreg8;
+ __IO uint8_t tmpreg8 = 0;
+
+ /* Adjust Timeout value in case of end of transfer */
+ tmp_timeout = Timeout - (HAL_GetTick() - Tickstart);
+ tmp_tickstart = HAL_GetTick();
+
+ /* Initialize the 8bit temporary pointer */
+ ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+
+ /* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */
+ count = tmp_timeout * ((SystemCoreClock * 35U) >> 20U);
+
+ while ((hspi->Instance->SR & Fifo) != State)
+ {
+ if ((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY))
+ {
+ /* Flush Data Register by a blank read */
+ tmpreg8 = *ptmpreg8;
+ /* To avoid GCC warning */
+ UNUSED(tmpreg8);
+ }
+
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
+ {
+ /* Disable the SPI and reset the CRC: the CRC value should be cleared
+ on both master and slave sides in order to resynchronize the master
+ and slave for their respective CRC calculation */
+
+ /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_TIMEOUT;
+ }
+ /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
+ if (count == 0U)
+ {
+ tmp_timeout = 0U;
+ }
+ else
+ {
+ count--;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle the check of the RX transaction complete.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Timeout Timeout duration
+ * @param Tickstart tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
+{
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ }
+
+ /* Control the BSY flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ return HAL_TIMEOUT;
+ }
+
+ if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, Timeout, Tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle the check of the RXTX or TX transaction complete.
+ * @param hspi SPI handle
+ * @param Timeout Timeout duration
+ * @param Tickstart tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
+{
+ /* Control if the TX fifo is empty */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FTLVL, SPI_FTLVL_EMPTY, Timeout, Tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ return HAL_TIMEOUT;
+ }
+
+ /* Control the BSY flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ return HAL_TIMEOUT;
+ }
+
+ /* Control if the RX fifo is empty */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, Timeout, Tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ return HAL_TIMEOUT;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle the end of the RXTX transaction.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi)
+{
+ uint32_t tickstart;
+
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+
+ /* Disable ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+
+#if (USE_SPI_CRC != 0U)
+ /* Check if CRC error occurred */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+#endif /* USE_SPI_CRC */
+ if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+ {
+ if (hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->RxCpltCallback(hspi);
+#else
+ HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Call user TxRx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->TxRxCpltCallback(hspi);
+#else
+ HAL_SPI_TxRxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+#if (USE_SPI_CRC != 0U)
+ }
+#endif /* USE_SPI_CRC */
+}
+
+/**
+ * @brief Handle the end of the RX transaction.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi)
+{
+ /* Disable RXNE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+ hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_SPI_CRC != 0U)
+ /* Check if CRC error occurred */
+ if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+#endif /* USE_SPI_CRC */
+ if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+ {
+ /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->RxCpltCallback(hspi);
+#else
+ HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+#if (USE_SPI_CRC != 0U)
+ }
+#endif /* USE_SPI_CRC */
+}
+
+/**
+ * @brief Handle the end of the TX transaction.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi)
+{
+ uint32_t tickstart;
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ /* Disable TXE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
+
+ /* Check the end of the transaction */
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+ }
+
+ /* Clear overrun flag in 2 Lines communication mode because received is not read */
+ if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+ if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->ErrorCallback(hspi);
+#else
+ HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+ hspi->TxCpltCallback(hspi);
+#else
+ HAL_SPI_TxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Handle abort a Rx transaction.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi)
+{
+ __IO uint32_t count;
+
+ /* Disable SPI Peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+
+ /* Disable RXNEIE interrupt */
+ CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXNEIE));
+
+ /* Check RXNEIE is disabled */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE));
+
+ /* Control the BSY flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ hspi->State = HAL_SPI_STATE_ABORT;
+}
+
+/**
+ * @brief Handle abort a Tx or Rx/Tx transaction.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi)
+{
+ __IO uint32_t count;
+
+ count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+
+ /* Disable TXEIE interrupt */
+ CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE));
+
+ /* Check TXEIE is disabled */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE));
+
+ if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Disable SPI Peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Check case of Full-Duplex Mode and disable directly RXNEIE interrupt */
+ if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
+ {
+ /* Disable RXNEIE interrupt */
+ CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXNEIE));
+
+ /* Check RXNEIE is disabled */
+ do
+ {
+ if (count == 0U)
+ {
+ SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+ break;
+ }
+ count--;
+ } while (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE));
+
+ /* Control the BSY flag */
+ if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+
+ /* Empty the FRLVL fifo */
+ if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+ HAL_GetTick()) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+ }
+ }
+ hspi->State = HAL_SPI_STATE_ABORT;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi_ex.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi_ex.c
new file mode 100644
index 0000000..f8a8a9f
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_spi_ex.c
@@ -0,0 +1,112 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_spi_ex.c
+ * @author MCD Application Team
+ * @brief Extended SPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * SPI peripheral extended functionalities :
+ * + IO operation functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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 "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPIEx SPIEx
+ * @brief SPI Extended HAL module driver
+ * @{
+ */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPIEx_Private_Constants SPIEx Private Constants
+ * @{
+ */
+#define SPI_FIFO_SIZE 4UL
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SPIEx_Exported_Functions SPIEx Exported Functions
+ * @{
+ */
+
+/** @defgroup SPIEx_Exported_Functions_Group1 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of extended functions to manage the SPI
+ data transfers.
+
+ (#) Rx data flush function:
+ (++) HAL_SPIEx_FlushRxFifo()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Flush the RX fifo.
+ * @param hspi pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi)
+{
+ __IO uint32_t tmpreg;
+ uint8_t count = 0U;
+ while ((hspi->Instance->SR & SPI_FLAG_FRLVL) != SPI_FRLVL_EMPTY)
+ {
+ count++;
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ if (count == SPI_FIFO_SIZE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c
new file mode 100644
index 0000000..0219ee8
--- /dev/null
+++ b/firmware/rf test/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c
@@ -0,0 +1,1361 @@
+/**
+ ******************************************************************************
+ * @file stm32wbxx_ll_rcc.c
+ * @author MCD Application Team
+ * @brief RCC LL module driver.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 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.
+ *
+ ******************************************************************************
+ */
+#if defined(USE_FULL_LL_DRIVER)
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_ll_rcc.h"
+#ifdef USE_FULL_ASSERT
+#include "stm32_assert.h"
+#else
+#define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+/** @addtogroup STM32WBxx_LL_Driver
+ * @{
+ */
+
+#if defined(RCC)
+
+/** @addtogroup RCC_LL
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup RCC_LL_Private_Macros
+ * @{
+ */
+#define IS_LL_RCC_USART_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_USART1_CLKSOURCE)
+
+#if defined(LPUART1)
+#define IS_LL_RCC_LPUART_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_LPUART1_CLKSOURCE)
+#endif /* LPUART1 */
+
+#if defined(I2C3)
+#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE))
+#else
+#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_I2C1_CLKSOURCE)
+#endif /* I2C3 */
+
+#define IS_LL_RCC_LPTIM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPTIM1_CLKSOURCE) \
+ || ((__VALUE__) == LL_RCC_LPTIM2_CLKSOURCE))
+
+#if defined(SAI1)
+#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_SAI1_CLKSOURCE)
+#endif /* SAI1 */
+
+#define IS_LL_RCC_RNG_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_RNG_CLKSOURCE))
+
+#define IS_LL_RCC_CLK48_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_CLK48_CLKSOURCE))
+
+#if defined(USB)
+#define IS_LL_RCC_USB_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USB_CLKSOURCE))
+#endif /* USB */
+
+#define IS_LL_RCC_ADC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_ADC_CLKSOURCE))
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup RCC_LL_Private_Functions RCC Private functions
+ * @{
+ */
+static uint32_t RCC_PLL_GetFreqDomain_SYS(void);
+#if defined(SAI1)
+static uint32_t RCC_PLL_GetFreqDomain_SAI(void);
+#endif /* SAI1 */
+static uint32_t RCC_PLL_GetFreqDomain_ADC(void);
+static uint32_t RCC_PLL_GetFreqDomain_48M(void);
+
+#if defined(SAI1)
+static uint32_t RCC_PLLSAI1_GetFreqDomain_SAI(void);
+static uint32_t RCC_PLLSAI1_GetFreqDomain_48M(void);
+static uint32_t RCC_PLLSAI1_GetFreqDomain_ADC(void);
+#endif /* SAI1 */
+
+
+static uint32_t RCC_GetSystemClockFreq(void);
+
+
+static uint32_t RCC_GetHCLK1ClockFreq(uint32_t SYSCLK_Frequency);
+static uint32_t RCC_GetHCLK2ClockFreq(uint32_t SYSCLK_Frequency);
+static uint32_t RCC_GetHCLK4ClockFreq(uint32_t SYSCLK_Frequency);
+static uint32_t RCC_GetHCLK5ClockFreq(void);
+
+
+static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency);
+static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency);
+/**
+ * @}
+ */
+
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup RCC_LL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RCC_LL_EF_Init
+ * @{
+ */
+
+/**
+ * @brief Reset the RCC clock to the default reset state.
+ * @note The default reset state of the clock configuration is given below:
+ * - MSI ON and used as system clock source
+ * - HSE, HSI, HSI48, PLL and PLLSAI1 Source OFF
+ * - CPU1, CPU2, AHB4, APB1 and APB2 prescaler set to 1.
+ * - CSS, MCO OFF
+ * - All interrupts disabled
+ * @note This function doesn't modify the configuration of the
+ * - Peripheral clocks
+ * - LSI, LSE and RTC clocks
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RCC registers are de-initialized
+ * - ERROR: not applicable
+ */
+ErrorStatus LL_RCC_DeInit(void)
+{
+ uint32_t vl_mask;
+
+ /* Set MSION bit */
+ LL_RCC_MSI_Enable();
+
+ /* Insure MSIRDY bit is set before writing default MSIRANGE value */
+ while (LL_RCC_MSI_IsReady() == 0U)
+ {}
+
+ /* Set MSIRANGE default value */
+ LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
+
+ /* Set MSITRIM bits to the reset value*/
+ LL_RCC_MSI_SetCalibTrimming(0);
+
+ /* Set HSITRIM bits to the reset value*/
+ LL_RCC_HSI_SetCalibTrimming(0x40U);
+
+ /* Reset CFGR register */
+ LL_RCC_WriteReg(CFGR, 0x00070000U); /* MSI selected as System Clock and all prescaler to not divided */
+
+ /* Wait for MSI oscillator used as system clock */
+ while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI)
+ {}
+
+ /* Write new mask in CR register */
+ LL_RCC_WriteReg(CR, 0x00000061);
+
+ /* Wait for PLL READY bit to be reset */
+ while (LL_RCC_PLL_IsReady() != 0U)
+ {}
+
+ /* Reset PLLCFGR register */
+ LL_RCC_WriteReg(PLLCFGR, 0x22041000U);
+
+#if defined(SAI1)
+ /* Wait for PLLSAI READY bit to be reset */
+ while (LL_RCC_PLLSAI1_IsReady() != 0U)
+ {}
+
+ /* Reset PLLSAI1CFGR register */
+ LL_RCC_WriteReg(PLLSAI1CFGR, 0x22041000U);
+#endif /* SAI1 */
+
+ /* Disable all interrupts */
+ LL_RCC_WriteReg(CIER, 0x00000000U);
+
+ /* Clear all interrupt flags */
+ vl_mask = RCC_CICR_LSI1RDYC | RCC_CICR_LSERDYC | RCC_CICR_MSIRDYC | RCC_CICR_HSIRDYC | RCC_CICR_HSERDYC |
+ RCC_CICR_PLLRDYC | RCC_CICR_CSSC | RCC_CICR_LSECSSC | RCC_CICR_LSI2RDYC;
+
+#if defined(SAI1)
+ vl_mask |= RCC_CICR_PLLSAI1RDYC;
+#endif /* SAI1 */
+
+#if defined(RCC_HSI48_SUPPORT)
+ vl_mask |= RCC_CICR_HSI48RDYC;
+#endif /* RCC_HSI48_SUPPORT */
+
+ LL_RCC_WriteReg(CICR, vl_mask);
+
+ /* Clear reset flags */
+ LL_RCC_ClearResetFlags();
+
+#if defined(RCC_SMPS_SUPPORT)
+ /* SMPS reset */
+ LL_RCC_WriteReg(SMPSCR, 0x00000301U); /* MSI default clock source */
+#endif /* RCC_SMPS_SUPPORT */
+
+ /* RF Wakeup Clock Source selection */
+ LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_NONE);
+
+#if defined(RCC_HSI48_SUPPORT)
+ /* HSI48 reset */
+ LL_RCC_HSI48_Disable();
+#endif /* RCC_HSI48_SUPPORT */
+
+ /* HSECR register write unlock & then reset*/
+ LL_RCC_WriteReg(HSECR, HSE_CONTROL_UNLOCK_KEY);
+ LL_RCC_WriteReg(HSECR, LL_RCC_HSE_CURRENTMAX_3); /* HSEGMC set to default value 011, current max limit 1.13 mA/V */
+
+ /* EXTCFGR reset*/
+ LL_RCC_WriteReg(EXTCFGR, 0x00030000U);
+
+ return SUCCESS;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RCC_LL_EF_Get_Freq
+ * @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks
+ * and different peripheral clocks available on the device.
+ * @note If SYSCLK source is MSI, function returns values based on MSI values(*)
+ * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(**)
+ * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(***)
+ * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(***)
+ * or HSI_VALUE(**) or MSI values(*) multiplied/divided by the PLL factors.
+ * @note (*) MSI values are retrieved thanks to __LL_RCC_CALC_MSI_FREQ macro
+ * @note (**) HSI_VALUE is a constant defined in this file (default value
+ * 16 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note (***) HSE_VALUE is a constant defined in this file (default value
+ * 32 MHz), user has to ensure that HSE_VALUE is same as the real
+ * frequency of the crystal used. Otherwise, this function may
+ * have wrong result.
+ * @note The result of this function could be incorrect when using fractional
+ * value for HSE crystal.
+ * @note This function can be used by the user application to compute the
+ * baud-rate for the communication peripherals or configure other parameters.
+ * @{
+ */
+
+/**
+ * @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks
+ * @note Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function
+ * must be called to update structure fields. Otherwise, any
+ * configuration based on this function will be incorrect.
+ * @param RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies
+ * @retval None
+ */
+void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks)
+{
+ /* Get SYSCLK frequency */
+ RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq();
+
+ /* HCLK1 clock frequency */
+ RCC_Clocks->HCLK1_Frequency = RCC_GetHCLK1ClockFreq(RCC_Clocks->SYSCLK_Frequency);
+
+ /* HCLK2 clock frequency */
+ RCC_Clocks->HCLK2_Frequency = RCC_GetHCLK2ClockFreq(RCC_Clocks->SYSCLK_Frequency);
+
+ /* HCLK4 clock frequency */
+ RCC_Clocks->HCLK4_Frequency = RCC_GetHCLK4ClockFreq(RCC_Clocks->SYSCLK_Frequency);
+
+ /* HCLK5 clock frequency */
+ RCC_Clocks->HCLK5_Frequency = RCC_GetHCLK5ClockFreq();
+
+ /* PCLK1 clock frequency */
+ RCC_Clocks->PCLK1_Frequency = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK1_Frequency);
+
+ /* PCLK2 clock frequency */
+ RCC_Clocks->PCLK2_Frequency = RCC_GetPCLK2ClockFreq(RCC_Clocks->HCLK1_Frequency);
+}
+
+#if defined(RCC_SMPS_SUPPORT)
+/**
+ * @brief Return SMPS clock frequency
+ * @note This function is only applicable when CPU runs,
+ * When waking up from Standby mode and powering on the VCODE supply, the HSI is
+ * selected as SMPS Step Down converter clock, independent from the selection in
+ * SMPSSEL.
+ * @retval SMPS clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
+ */
+uint32_t LL_RCC_GetSMPSClockFreq(void)
+{
+ uint32_t smps_frequency;
+ uint32_t smps_prescaler_index = ((LL_RCC_GetSMPSPrescaler()) >> RCC_SMPSCR_SMPSDIV_Pos);
+ uint32_t smpsClockSource = LL_RCC_GetSMPSClockSource();
+
+ if (smpsClockSource == LL_RCC_SMPS_CLKSOURCE_STATUS_HSI) /* SMPS Clock source is HSI Osc. */
+ {
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ smps_frequency = HSI_VALUE / SmpsPrescalerTable[smps_prescaler_index][0];
+ }
+ else
+ {
+ smps_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ }
+ }
+ else if (smpsClockSource == LL_RCC_SMPS_CLKSOURCE_STATUS_HSE) /* SMPS Clock source is HSE Osc. */
+ {
+ if (LL_RCC_HSE_IsReady() == 1U)
+ {
+ smps_frequency = HSE_VALUE / SmpsPrescalerTable[smps_prescaler_index][5];
+ }
+ else
+ {
+ smps_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ }
+ }
+ else if (smpsClockSource == LL_RCC_SMPS_CLKSOURCE_STATUS_MSI) /* SMPS Clock source is MSI Osc. */
+ {
+ uint32_t msiRange = LL_RCC_MSI_GetRange();
+
+ if (msiRange == LL_RCC_MSIRANGE_8)
+ {
+ smps_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_8) / SmpsPrescalerTable[smps_prescaler_index][4];
+ }
+ else if (msiRange == LL_RCC_MSIRANGE_9)
+ {
+ smps_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_9) / SmpsPrescalerTable[smps_prescaler_index][3];
+ }
+ else if (msiRange == LL_RCC_MSIRANGE_10)
+ {
+ smps_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_10) / SmpsPrescalerTable[smps_prescaler_index][2];
+ }
+ else if (msiRange == LL_RCC_MSIRANGE_11)
+ {
+ smps_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGE_11) / SmpsPrescalerTable[smps_prescaler_index][1];
+ }
+ else
+ {
+ smps_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ }
+ }
+ else /* SMPS has no Clock */
+ {
+ smps_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ }
+
+ if (smps_frequency != LL_RCC_PERIPH_FREQUENCY_NO)
+ {
+ /* Systematic div by 2 */
+ smps_frequency = smps_frequency >> 1U;
+ }
+
+ return smps_frequency;
+}
+#endif /* RCC_SMPS_SUPPORT */
+
+/**
+ * @brief Return USARTx clock frequency
+ * @param USARTxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_USART1_CLKSOURCE
+ * @retval USART clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
+ */
+uint32_t LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource)
+{
+ uint32_t usart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_USART_CLKSOURCE(USARTxSource));
+
+ /* USART1CLK clock frequency */
+ switch (LL_RCC_GetUSARTClockSource(USARTxSource))
+ {
+ case LL_RCC_USART1_CLKSOURCE_SYSCLK: /* USART1 Clock is System Clock */
+ usart_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_USART1_CLKSOURCE_HSI: /* USART1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ usart_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_USART1_CLKSOURCE_LSE: /* USART1 Clock is LSE Osc. */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ usart_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_USART1_CLKSOURCE_PCLK2: /* USART1 Clock is PCLK2 */
+ default:
+ usart_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLK1ClockFreq(RCC_GetSystemClockFreq()));
+ break;
+ }
+ return usart_frequency;
+}
+
+/**
+ * @brief Return I2Cx clock frequency
+ * @param I2CxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_I2C1_CLKSOURCE
+ * @arg @ref LL_RCC_I2C3_CLKSOURCE (*)
+ * @note (*) Value not defined for all devices
+ * @retval I2C clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that HSI oscillator is not ready
+ */
+uint32_t LL_RCC_GetI2CClockFreq(uint32_t I2CxSource)
+{
+ uint32_t i2c_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_I2C_CLKSOURCE(I2CxSource));
+
+ if (I2CxSource == LL_RCC_I2C1_CLKSOURCE)
+ {
+ /* I2C1 CLK clock frequency */
+ switch (LL_RCC_GetI2CClockSource(I2CxSource))
+ {
+ case LL_RCC_I2C1_CLKSOURCE_SYSCLK: /* I2C1 Clock is System Clock */
+ i2c_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_I2C1_CLKSOURCE_HSI: /* I2C1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ i2c_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_I2C1_CLKSOURCE_PCLK1: /* I2C1 Clock is PCLK1 */
+ default:
+ i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLK1ClockFreq(RCC_GetSystemClockFreq()));
+ break;
+ }
+ }
+#if defined(I2C3)
+ else
+ {
+ /* I2C3 CLK clock frequency */
+ switch (LL_RCC_GetI2CClockSource(I2CxSource))
+ {
+ case LL_RCC_I2C3_CLKSOURCE_SYSCLK: /* I2C3 Clock is System Clock */
+ i2c_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_I2C3_CLKSOURCE_HSI: /* I2C3 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ i2c_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_I2C3_CLKSOURCE_PCLK1: /* I2C3 Clock is PCLK1 */
+ default:
+ i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLK1ClockFreq(RCC_GetSystemClockFreq()));
+ break;
+ }
+ }
+#endif /* I2C3 */
+
+ return i2c_frequency;
+}
+
+#if defined(LPUART1)
+/**
+ * @brief Return LPUARTx clock frequency
+ * @param LPUARTxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_LPUART1_CLKSOURCE
+ * @retval LPUART clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
+ */
+uint32_t LL_RCC_GetLPUARTClockFreq(uint32_t LPUARTxSource)
+{
+ uint32_t lpuart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_LPUART_CLKSOURCE(LPUARTxSource));
+
+ /* LPUART1CLK clock frequency */
+ switch (LL_RCC_GetLPUARTClockSource(LPUARTxSource))
+ {
+ case LL_RCC_LPUART1_CLKSOURCE_SYSCLK: /* LPUART1 Clock is System Clock */
+ lpuart_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_HSI: /* LPUART1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ lpuart_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_LSE: /* LPUART1 Clock is LSE Osc. */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ lpuart_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPUART1_CLKSOURCE_PCLK1: /* LPUART1 Clock is PCLK1 */
+ default:
+ lpuart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLK1ClockFreq(RCC_GetSystemClockFreq()));
+ break;
+ }
+
+ return lpuart_frequency;
+}
+#endif /* LPUART1 */
+
+/**
+ * @brief Return LPTIMx clock frequency
+ * @param LPTIMxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_LPTIM1_CLKSOURCE
+ * @arg @ref LL_RCC_LPTIM2_CLKSOURCE
+ * @retval LPTIM clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI, LSI or LSE) is not ready
+ */
+uint32_t LL_RCC_GetLPTIMClockFreq(uint32_t LPTIMxSource)
+{
+ uint32_t lptim_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ uint32_t temp = LL_RCC_LSI2_IsReady();
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_LPTIM_CLKSOURCE(LPTIMxSource));
+
+ if (LPTIMxSource == LL_RCC_LPTIM1_CLKSOURCE)
+ {
+ /* LPTIM1CLK clock frequency */
+ switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource))
+ {
+ case LL_RCC_LPTIM1_CLKSOURCE_LSI: /* LPTIM1 Clock is LSI Osc. */
+ if ((LL_RCC_LSI1_IsReady() == 1UL) || (temp == 1UL))
+ {
+ lptim_frequency = LSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_HSI: /* LPTIM1 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ lptim_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_LSE: /* LPTIM1 Clock is LSE Osc. */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ lptim_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM1_CLKSOURCE_PCLK1: /* LPTIM1 Clock is PCLK1 */
+ default:
+ lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLK1ClockFreq(RCC_GetSystemClockFreq()));
+ break;
+ }
+ }
+ else
+ {
+ /* LPTIM2CLK clock frequency */
+ switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource))
+ {
+ case LL_RCC_LPTIM2_CLKSOURCE_LSI: /* LPTIM2 Clock is LSI Osc. */
+ if ((LL_RCC_LSI1_IsReady() == 1UL) || (temp == 1UL))
+ {
+ lptim_frequency = LSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM2_CLKSOURCE_HSI: /* LPTIM2 Clock is HSI Osc. */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ lptim_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM2_CLKSOURCE_LSE: /* LPTIM2 Clock is LSE Osc. */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ lptim_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_LPTIM2_CLKSOURCE_PCLK1: /* LPTIM2 Clock is PCLK1 */
+ default:
+ lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLK1ClockFreq(RCC_GetSystemClockFreq()));
+ break;
+ }
+ }
+
+ return lptim_frequency;
+}
+
+#if defined(SAI1)
+/**
+ * @brief Return SAIx clock frequency
+ * @param SAIxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_SAI1_CLKSOURCE
+ *
+ * @retval SAI clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that PLL is not ready
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that external clock is used
+ */
+uint32_t LL_RCC_GetSAIClockFreq(uint32_t SAIxSource)
+{
+ uint32_t sai_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_SAI_CLKSOURCE(SAIxSource));
+
+ switch (LL_RCC_GetSAIClockSource(SAIxSource))
+ {
+ case LL_RCC_SAI1_CLKSOURCE_HSI: /* HSI clock used as SAI1 clock source */
+ if (LL_RCC_HSI_IsReady() == 1U)
+ {
+ sai_frequency = HSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SAI1 clock source */
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ if (LL_RCC_PLLSAI1_IsEnabledDomain_SAI() == 1U)
+ {
+ sai_frequency = RCC_PLLSAI1_GetFreqDomain_SAI();
+ }
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PLL: /* PLL clock used as SAI1 clock source */
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ if (LL_RCC_PLL_IsEnabledDomain_SAI() == 1U)
+ {
+ sai_frequency = RCC_PLL_GetFreqDomain_SAI();
+ }
+ }
+ break;
+
+ case LL_RCC_SAI1_CLKSOURCE_PIN: /* External input clock used as SAI1 clock source */
+ default:
+ sai_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
+ break;
+ }
+ return sai_frequency;
+}
+#endif /* SAI1 */
+
+/**
+ * @brief Return CLK48x clock frequency
+ * @param CLK48xSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_CLK48_CLKSOURCE
+ * @retval USB clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI or HSI48) or PLLs (PLL or PLLSAI1)
+ * is not ready
+ */
+uint32_t LL_RCC_GetCLK48ClockFreq(uint32_t CLK48xSource)
+{
+ uint32_t clk48_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_CLK48_CLKSOURCE(CLK48xSource));
+
+ /* CLK48CLK clock frequency */
+ switch (LL_RCC_GetCLK48ClockSource(CLK48xSource))
+ {
+#if defined(SAI1)
+ case LL_RCC_CLK48_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as CLK48 clock source */
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() == 1U)
+ {
+ clk48_frequency = RCC_PLLSAI1_GetFreqDomain_48M();
+ }
+ }
+ break;
+#endif /* SAI1 */
+
+ case LL_RCC_CLK48_CLKSOURCE_PLL: /* PLL clock used as CLK48 clock source */
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ if (LL_RCC_PLL_IsEnabledDomain_48M() == 1U)
+ {
+ clk48_frequency = RCC_PLL_GetFreqDomain_48M();
+ }
+ }
+ break;
+
+ case LL_RCC_CLK48_CLKSOURCE_MSI: /* MSI clock used as CLK48 clock source */
+ if (LL_RCC_MSI_IsReady() == 1U)
+ {
+ clk48_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ }
+ break;
+
+#if defined(RCC_HSI48_SUPPORT)
+ case LL_RCC_CLK48_CLKSOURCE_HSI48: /* HSI48 clock used as CLK48 clock source */
+ default:
+ if (LL_RCC_HSI48_IsReady() == 1U)
+ {
+ clk48_frequency = HSI48_VALUE;
+ }
+ break;
+#else
+ default:
+ /* Nothing to do */
+ break;
+#endif /* RCC_HSI48_SUPPORT */
+ }
+
+ return clk48_frequency;
+}
+
+#if defined(USB)
+/**
+ * @brief Return USBx clock frequency
+ * @param USBxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_CLK48_CLKSOURCE
+ * @retval USB clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI or HSI48) or PLLs (PLL or PLLSAI1)
+ * is not ready
+ */
+uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource)
+{
+ return LL_RCC_GetCLK48ClockFreq(USBxSource);
+}
+#endif /* USB */
+
+/**
+ * @brief Return RNGx clock frequency
+ * @param RNGxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_RNG_CLKSOURCE
+ * @retval RNG clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI or HSI48) or PLLs (PLL or PLLSAI1)
+ * is not ready
+ */
+uint32_t LL_RCC_GetRNGClockFreq(uint32_t RNGxSource)
+{
+ uint32_t rng_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ uint32_t rngClockSource = LL_RCC_GetRNGClockSource(RNGxSource);
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_RNG_CLKSOURCE(RNGxSource));
+
+ /* RNGCLK clock frequency */
+ if (rngClockSource == LL_RCC_RNG_CLKSOURCE_LSI) /* LSI clock used as RNG clock source */
+ {
+ const uint32_t temp_lsi1Status = LL_RCC_LSI1_IsReady();
+ const uint32_t temp_lsi2Status = LL_RCC_LSI2_IsReady();
+ if ((temp_lsi1Status == 1U) || (temp_lsi2Status == 1U))
+ {
+ rng_frequency = LSI_VALUE;
+ }
+ }
+ else if (rngClockSource == LL_RCC_RNG_CLKSOURCE_LSE) /* LSE clock used as RNG clock source */
+ {
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ rng_frequency = LSE_VALUE;
+ }
+ }
+ else /* CLK48 clock used as RNG clock source */
+ {
+ /* Systematic Div by 3 */
+ rng_frequency = LL_RCC_GetCLK48ClockFreq(LL_RCC_CLK48_CLKSOURCE) / 3U;
+ }
+ return rng_frequency;
+}
+
+/**
+ * @brief Return ADCx clock frequency
+ * @param ADCxSource This parameter can be one of the following values:
+ * @arg @ref LL_RCC_ADC_CLKSOURCE
+ * @retval ADC clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
+ */
+uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource)
+{
+ uint32_t adc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* Check parameter */
+ assert_param(IS_LL_RCC_ADC_CLKSOURCE(ADCxSource));
+
+ /* ADCCLK clock frequency */
+ switch (LL_RCC_GetADCClockSource(ADCxSource))
+ {
+#if defined(SAI1)
+ case LL_RCC_ADC_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as ADC clock source */
+ if (LL_RCC_PLLSAI1_IsReady() == 1U)
+ {
+ if (LL_RCC_PLLSAI1_IsEnabledDomain_ADC() == 1U)
+ {
+ adc_frequency = RCC_PLLSAI1_GetFreqDomain_ADC();
+ }
+ }
+ break;
+#endif /* SAI1 */
+
+ case LL_RCC_ADC_CLKSOURCE_SYSCLK: /* SYSCLK clock used as ADC clock source */
+ adc_frequency = RCC_GetSystemClockFreq();
+ break;
+
+ case LL_RCC_ADC_CLKSOURCE_PLL: /* PLL clock used as ADC clock source */
+ if (LL_RCC_PLL_IsReady() == 1U)
+ {
+ if (LL_RCC_PLL_IsEnabledDomain_ADC() == 1U)
+ {
+ adc_frequency = RCC_PLL_GetFreqDomain_ADC();
+ }
+ }
+ break;
+
+ case LL_RCC_ADC_CLKSOURCE_NONE: /* No clock used as ADC clock source */
+ default:
+ adc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
+ break;
+ }
+
+ return adc_frequency;
+}
+
+/**
+ * @brief Return RTC & LCD clock frequency
+ * @retval RTC clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillators (LSI, LSE or HSE) are not ready
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
+ */
+uint32_t LL_RCC_GetRTCClockFreq(void)
+{
+ uint32_t rtc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+ uint32_t temp = LL_RCC_LSI2_IsReady();
+
+ /* RTCCLK clock frequency */
+ switch (LL_RCC_GetRTCClockSource())
+ {
+ case LL_RCC_RTC_CLKSOURCE_LSE: /* LSE clock used as RTC clock source */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ rtc_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_RTC_CLKSOURCE_LSI: /* LSI clock used as RTC clock source */
+
+ if ((LL_RCC_LSI1_IsReady() == 1UL) || (temp == 1UL))
+ {
+ rtc_frequency = LSI_VALUE;
+ }
+ break;
+
+ case LL_RCC_RTC_CLKSOURCE_HSE_DIV32: /* HSE clock used as ADC clock source */
+ rtc_frequency = HSE_VALUE / 32U;
+ break;
+
+ case LL_RCC_RTC_CLKSOURCE_NONE: /* No clock used as RTC clock source */
+ default:
+ rtc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
+ break;
+ }
+
+ return rtc_frequency;
+}
+
+/**
+ * @brief Return RF Wakeup clock frequency
+ * @retval RFWKP clock frequency (in Hz)
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillators (LSI, LSE or HSE) are not ready
+ * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
+ */
+uint32_t LL_RCC_GetRFWKPClockFreq(void)
+{
+ uint32_t rfwkp_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
+
+ /* RTCCLK clock frequency */
+ switch (LL_RCC_GetRFWKPClockSource())
+ {
+ case LL_RCC_RFWKP_CLKSOURCE_LSE: /* LSE clock used as RF Wakeup clock source */
+ if (LL_RCC_LSE_IsReady() == 1U)
+ {
+ rfwkp_frequency = LSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_RFWKP_CLKSOURCE_HSE_DIV1024: /* HSE clock used as RF Wakeup clock source */
+ rfwkp_frequency = HSE_VALUE / 1024U;
+ break;
+
+ case LL_RCC_RFWKP_CLKSOURCE_NONE: /* No clock used as RF Wakeup clock source */
+ default:
+ rfwkp_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
+ break;
+ }
+
+ return rfwkp_frequency;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RCC_LL_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Return SYSTEM clock (SYSCLK) frequency
+ * @retval SYSTEM clock frequency (in Hz)
+ */
+static uint32_t RCC_GetSystemClockFreq(void)
+{
+ uint32_t frequency;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ switch (LL_RCC_GetSysClkSource())
+ {
+ case LL_RCC_SYS_CLKSOURCE_STATUS_MSI: /* MSI used as system clock source */
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_SYS_CLKSOURCE_STATUS_HSI: /* HSI used as system clock source */
+ frequency = HSI_VALUE;
+ break;
+
+ case LL_RCC_SYS_CLKSOURCE_STATUS_HSE: /* HSE used as system clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ frequency = HSE_VALUE / 2U;
+ }
+ else
+ {
+ frequency = HSE_VALUE;
+ }
+ break;
+
+ case LL_RCC_SYS_CLKSOURCE_STATUS_PLL: /* PLL used as system clock source */
+ frequency = RCC_PLL_GetFreqDomain_SYS();
+ break;
+
+ default:
+ frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+
+ return frequency;
+}
+
+/**
+ * @brief Return HCLK1 clock frequency
+ * @param SYSCLK_Frequency SYSCLK clock frequency
+ * @retval HCLK1 clock frequency (in Hz)
+ */
+static uint32_t RCC_GetHCLK1ClockFreq(uint32_t SYSCLK_Frequency)
+{
+ /* HCLK clock frequency */
+ return __LL_RCC_CALC_HCLK1_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler());
+}
+
+/**
+ * @brief Return HCLK2 clock frequency
+ * @param SYSCLK_Frequency SYSCLK clock frequency
+ * @retval HCLK2 clock frequency (in Hz)
+ */
+static uint32_t RCC_GetHCLK2ClockFreq(uint32_t SYSCLK_Frequency)
+{
+ /* HCLK clock frequency */
+ return __LL_RCC_CALC_HCLK2_FREQ(SYSCLK_Frequency, LL_C2_RCC_GetAHBPrescaler());
+}
+
+/**
+ * @brief Return HCLK clock frequency
+ * @param SYSCLK_Frequency SYSCLK clock frequency
+ * @retval HCLK4 clock frequency (in Hz)
+ */
+static uint32_t RCC_GetHCLK4ClockFreq(uint32_t SYSCLK_Frequency)
+{
+ /* HCLK clock frequency */
+ return __LL_RCC_CALC_HCLK4_FREQ(SYSCLK_Frequency, LL_RCC_GetAHB4Prescaler());
+}
+
+/**
+ * @brief Return HCLK5 clock frequency
+ * @retval HCLK5 clock frequency (in Hz)
+ */
+static uint32_t RCC_GetHCLK5ClockFreq(void)
+{
+ uint32_t frequency;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ switch (LL_RCC_GetRFClockSource())
+ {
+ case LL_RCC_RF_CLKSOURCE_HSI: /* HSI used as system clock source */
+ frequency = HSI_VALUE;
+ break;
+
+ case LL_RCC_RF_CLKSOURCE_HSE_DIV2: /* HSE Div2 used as system clock source */
+ frequency = HSE_VALUE / 2U;
+ break;
+
+ default:
+ frequency = HSI_VALUE;
+ break;
+ }
+
+ return frequency;
+}
+
+/**
+ * @brief Return PCLK1 clock frequency
+ * @param HCLK_Frequency HCLK clock frequency
+ * @retval PCLK1 clock frequency (in Hz)
+ */
+static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)
+{
+ /* PCLK1 clock frequency */
+ return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler());
+}
+
+/**
+ * @brief Return PCLK2 clock frequency
+ * @param HCLK_Frequency HCLK clock frequency
+ * @retval PCLK2 clock frequency (in Hz)
+ */
+static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency)
+{
+ /* PCLK2 clock frequency */
+ return __LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler());
+}
+
+/**
+ * @brief Return PLL clock (PLLRCLK) frequency used for system domain
+ * @retval PLLRCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLL_GetFreqDomain_SYS(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLN
+ SYSCLK = PLL_VCO / PLLR
+ */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR());
+}
+
+#if defined(SAI1)
+/**
+ * @brief Return PLL clock (PLLPCLK) frequency used for SAI domain
+ * @retval PLLPCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLL_GetFreqDomain_SAI(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI Value / PLLM) * PLLN
+ SAI Domain clock = PLL_VCO / PLLP
+ */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLCLK_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLL_GetN(), LL_RCC_PLL_GetP());
+}
+#endif /* SAI1 */
+
+/**
+ * @brief Return PLL clock (PLLPCLK) frequency used for ADC domain
+ * @retval PLLPCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLL_GetFreqDomain_ADC(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI Value / PLLM) * PLLN
+ SAI Domain clock = PLL_VCO / PLLP
+ */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLCLK_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLL_GetN(), LL_RCC_PLL_GetP());
+}
+
+/**
+ * @brief Return PLL clock (PLLQCLK) frequency used for 48 MHz domain
+ * @retval PLLQCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLL_GetFreqDomain_48M(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLN
+ 48M Domain clock = PLL_VCO / PLLQ
+ */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLCLK_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLL_GetN(), LL_RCC_PLL_GetQ());
+}
+
+#if defined(SAI1)
+/**
+ * @brief Return PLLSAI1 clock (PLLSAI1PCLK) frequency used for SAI domain
+ * @retval PLLSAI1PCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLLSAI1_GetFreqDomain_SAI(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLSAI1N */
+ /* SAI Domain clock = PLLSAI1_VCO / PLLSAI1P */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLSAI1_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetP());
+}
+
+/**
+ * @brief Return PLLSAI1 clock (PLLSAI1QCLK) frequency used for 48Mhz domain
+ * @retval PLLSAI1QCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLLSAI1_GetFreqDomain_48M(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLSAI1N */
+ /* 48M Domain clock = PLLSAI1_VCO / PLLSAI1Q */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLSAI1_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetQ());
+}
+
+/**
+ * @brief Return PLLSAI1 clock (PLLSAI1RCLK) frequency used for ADC domain
+ * @retval PLLSAI1RCLK clock frequency (in Hz)
+ */
+static uint32_t RCC_PLLSAI1_GetFreqDomain_ADC(void)
+{
+ uint32_t pllinputfreq;
+ uint32_t pllsource;
+
+ /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI Value/ PLLM) * PLLSAI1N */
+ /* 48M Domain clock = PLLSAI1_VCO / PLLSAI1R */
+ pllsource = LL_RCC_PLL_GetMainSource();
+
+ switch (pllsource)
+ {
+ case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+
+ case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
+ pllinputfreq = HSI_VALUE;
+ break;
+
+ case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
+ if (LL_RCC_HSE_IsEnabledDiv2() == 1U)
+ {
+ pllinputfreq = HSE_VALUE / 2U;
+ }
+ else
+ {
+ pllinputfreq = HSE_VALUE;
+ }
+ break;
+
+ default:
+ pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
+ break;
+ }
+ return __LL_RCC_CALC_PLLSAI1_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
+ LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetR());
+}
+#endif /* SAI1 */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* RCC */
+
+/**
+ * @}
+ */
+
+#endif /* USE_FULL_LL_DRIVER */