MX 2 лет назад
Сommit
fa001c773c

+ 48 - 0
README.md

@@ -0,0 +1,48 @@
+# flipperscope
+
+To compile and install
+
+```
+cd flipperzero-firmware/applications_user
+git clone https://github.com/anfractuosity/flipperscope.git
+cd ..
+./fbt DEBUG=1 VERBOSE=1 fap_scope
+./fbt launch_app APPSRC=applications_user/flipperscope
+```
+
+Alternatively upload the **scope.fap** file in the binary folder of this repository to your flipper zero.
+
+Provide signal to **pin 16/PC0**, with a voltage ranging from 0V to 2.5V and ground to **pin 18/GND**.
+
+Press the 'ok' button (button in the centre of joypad) to pause/unpause the waveform display.
+
+[Demo](https://www.youtube.com/watch?v=tu2X1WwADF4) showing three different waveform types from a signal generator.
+
+Also see [Derek Jamison's demonstration](https://www.youtube.com/watch?v=iC5fBGwCPHw&t=374s) of this app as well as other interesting projects.
+
+## Measurements
+
+* Measures frequency of waveform in hertz
+* Measures voltage: min, max, Vpp
+
+![Signal Generator](photos/sig.jpg)
+
+![Flipper Zero running flipperscope](photos/freq.jpg)
+
+![Rigol](photos/rigol.jpg)
+
+![Flipper Zero running flipperscope](photos/volt.jpg)
+
+## To Do
+
+* Customisable input pin
+* Trigger type mode
+* FFT
+* ...
+
+## Inspiration
+
+* For GUI menu system, used code principles from weather station and signal generator apps
+* STM32 DMA example
+* VREFBUF information - https://community.st.com/s/question/0D53W00001awIlMSAU/enable-and-use-vrefbuf-for-adc-measures
+* Relocating vector table - https://community.nxp.com/t5/i-MX-Processors/Relocate-vector-table-to-ITCM/m-p/1302304

+ 29 - 0
application.fam

@@ -0,0 +1,29 @@
+App(
+    appid="scope",
+    name="Scope",
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="scope_main",
+    requires=["gui"],
+    stack_size=1 * 1024,
+    fap_category="GPIO",
+    fap_icon="scope_10px.png",
+    fap_private_libs=[
+        Lib(
+            name="adc",
+            fap_include_paths=["inc"],
+            sources=[
+                "stm32wbxx_hal_adc.c",
+                "stm32wbxx_hal_adc_ex.c",
+                "stm32wbxx_hal_rcc_ex.c",
+                "stm32wbxx_hal_gpio.c",
+                "stm32wbxx_hal_pwr.c",
+                "stm32wbxx_hal.c",
+                "stm32wbxx_hal_tim.c",
+                "stm32wbxx_hal_tim_ex.c",
+                "stm32wbxx_hal_cortex.c",
+                "stm32wbxx_hal_dma.c",
+                "stm32wbxx_hal_rcc.c",
+            ],
+        )
+    ],
+)

+ 352 - 0
lib/adc/inc/stm32wbxx_hal_conf.h

@@ -0,0 +1,352 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_conf.h
+  * @author  MCD Application Team
+  * @brief   HAL configuration file.
+  ******************************************************************************
+  * @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.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32WBxx_HAL_CONF_H
+#define __STM32WBxx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+  * @brief This is the list of modules to be used in the HAL driver
+  */
+#define HAL_MODULE_ENABLED
+#define HAL_ADC_MODULE_ENABLED
+/*#define HAL_CRYP_MODULE_ENABLED   */
+/*#define HAL_COMP_MODULE_ENABLED   */
+/*#define HAL_CRC_MODULE_ENABLED   */
+/*#define HAL_HSEM_MODULE_ENABLED   */
+/*#define HAL_I2C_MODULE_ENABLED   */
+/*#define HAL_IPCC_MODULE_ENABLED   */
+/*#define HAL_IRDA_MODULE_ENABLED   */
+/*#define HAL_IWDG_MODULE_ENABLED   */
+/*#define HAL_LCD_MODULE_ENABLED   */
+/*#define HAL_LPTIM_MODULE_ENABLED   */
+/*#define HAL_PCD_MODULE_ENABLED   */
+/*#define HAL_PKA_MODULE_ENABLED   */
+/*#define HAL_QSPI_MODULE_ENABLED   */
+/*#define HAL_RNG_MODULE_ENABLED   */
+/*#define HAL_RTC_MODULE_ENABLED   */
+/*#define HAL_SAI_MODULE_ENABLED   */
+/*#define HAL_SMBUS_MODULE_ENABLED   */
+/*#define HAL_SMARTCARD_MODULE_ENABLED   */
+/*#define HAL_SPI_MODULE_ENABLED   */
+#define HAL_TIM_MODULE_ENABLED
+/*#define HAL_TSC_MODULE_ENABLED   */
+/*#define HAL_UART_MODULE_ENABLED   */
+/*#define HAL_USART_MODULE_ENABLED   */
+/*#define HAL_WWDG_MODULE_ENABLED   */
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+
+#define USE_HAL_ADC_REGISTER_CALLBACKS       0u
+#define USE_HAL_COMP_REGISTER_CALLBACKS      0u
+#define USE_HAL_CRYP_REGISTER_CALLBACKS      0u
+#define USE_HAL_I2C_REGISTER_CALLBACKS       0u
+#define USE_HAL_IRDA_REGISTER_CALLBACKS      0u
+#define USE_HAL_LPTIM_REGISTER_CALLBACKS     0u
+#define USE_HAL_PCD_REGISTER_CALLBACKS       0u
+#define USE_HAL_PKA_REGISTER_CALLBACKS       0u
+#define USE_HAL_QSPI_REGISTER_CALLBACKS      0u
+#define USE_HAL_RNG_REGISTER_CALLBACKS       0u
+#define USE_HAL_RTC_REGISTER_CALLBACKS       0u
+#define USE_HAL_SAI_REGISTER_CALLBACKS       0u
+#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0u
+#define USE_HAL_SMBUS_REGISTER_CALLBACKS     0u
+#define USE_HAL_SPI_REGISTER_CALLBACKS       0u
+#define USE_HAL_TIM_REGISTER_CALLBACKS       0u
+#define USE_HAL_TSC_REGISTER_CALLBACKS       0u
+#define USE_HAL_UART_REGISTER_CALLBACKS      0u
+#define USE_HAL_USART_REGISTER_CALLBACKS     0u
+#define USE_HAL_WWDG_REGISTER_CALLBACKS      0u
+
+/* ########################## Oscillator Values adaptation ####################*/
+/**
+  * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSE is used as system clock source, directly or through the PLL).
+  */
+#if !defined  (HSE_VALUE)
+#define HSE_VALUE    8000000U             /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined  (HSE_STARTUP_TIMEOUT)
+  #define HSE_STARTUP_TIMEOUT    ((uint32_t)100)   /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief Internal Multiple Speed oscillator (MSI) default value.
+  *        This value is the default MSI range value after Reset.
+  */
+#if !defined  (MSI_VALUE)
+  #define MSI_VALUE    ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* MSI_VALUE */
+
+/**
+  * @brief Internal High Speed oscillator (HSI) value.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSI is used as system clock source, directly or through the PLL).
+  */
+#if !defined  (HSI_VALUE)
+#define HSI_VALUE    16000000U            /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+  * @brief Internal Low Speed oscillator (LSI1) value.
+  */
+#if !defined  (LSI1_VALUE)
+ #define LSI1_VALUE  ((uint32_t)32000)       /*!< LSI1 Typical Value in Hz*/
+#endif /* LSI1_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.*/
+/**
+  * @brief Internal Low Speed oscillator (LSI2) value.
+  */
+#if !defined  (LSI2_VALUE)
+ #define LSI2_VALUE  ((uint32_t)32000)       /*!< LSI2 Typical Value in Hz*/
+#endif /* LSI2_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.*/
+
+/**
+  * @brief External Low Speed oscillator (LSE) value.
+  *        This value is used by the UART, RTC HAL module to compute the system frequency
+  */
+#if !defined  (LSE_VALUE)
+#define LSE_VALUE    32768U               /*!< Value of the External oscillator in Hz*/
+#endif /* LSE_VALUE */
+
+/**
+  * @brief Internal Multiple Speed oscillator (HSI48) default value.
+  *        This value is the default HSI48 range value after Reset.
+  */
+#if !defined (HSI48_VALUE)
+  #define HSI48_VALUE    ((uint32_t)48000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI48_VALUE */
+
+#if !defined  (LSE_STARTUP_TIMEOUT)
+#define LSE_STARTUP_TIMEOUT    5000U      /*!< Time out for LSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief External clock source for SAI1 peripheral
+  *        This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
+  *        frequency.
+  */
+#if !defined (EXTERNAL_SAI1_CLOCK_VALUE)
+  #define EXTERNAL_SAI1_CLOCK_VALUE    ((uint32_t)2097000) /*!< Value of the SAI1 External clock source in Hz*/
+#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+   ===  you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+  * @brief This is the HAL system configuration section
+  */
+
+#define  VDD_VALUE				3300U                   /*!< Value of VDD in mv */
+#define  TICK_INT_PRIORITY            0U      /*!< tick interrupt priority */
+#define  USE_RTOS                     0U
+#define  PREFETCH_ENABLE              1U
+#define  INSTRUCTION_CACHE_ENABLE     1U
+#define  DATA_CACHE_ENABLE            1U
+
+/* ########################## Assert Selection ############################## */
+/**
+  * @brief Uncomment the line below to expanse the "assert_param" macro in the
+  *        HAL drivers code
+  */
+/* #define USE_FULL_ASSERT    1U */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+ * Activated: CRC code is present inside driver
+ * Deactivated: CRC code cleaned from driver
+ */
+
+#define USE_SPI_CRC                   0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+  * @brief Include module's header file
+  */
+#ifdef HAL_DMA_MODULE_ENABLED
+  #include "stm32wbxx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+  #include "stm32wbxx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_COMP_MODULE_ENABLED
+  #include "stm32wbxx_hal_comp.h"
+#endif /* HAL_COMP_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+  #include "stm32wbxx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+  #include "stm32wbxx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+  #include "stm32wbxx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+  #include "stm32wbxx_hal_exti.h"
+#endif /* HAL_EXTI_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+  #include "stm32wbxx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+  #include "stm32wbxx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+  #include "stm32wbxx_hal_hsem.h"
+#endif /* HAL_HSEM_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32wbxx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_IPCC_MODULE_ENABLED
+ #include "stm32wbxx_hal_ipcc.h"
+#endif /* HAL_IPCC_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32wbxx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32wbxx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LCD_MODULE_ENABLED
+ #include "stm32wbxx_hal_lcd.h"
+#endif /* HAL_LCD_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+  #include "stm32wbxx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+  #include "stm32wbxx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_PKA_MODULE_ENABLED
+  #include "stm32wbxx_hal_pka.h"
+#endif /* HAL_PKA_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32wbxx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32wbxx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+  #include "stm32wbxx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+  #include "stm32wbxx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32wbxx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32wbxx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32wbxx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_SMBUS_MODULE_ENABLED
+ #include "stm32wbxx_hal_smbus.h"
+#endif /* HAL_SMBUS_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32wbxx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32wbxx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_TSC_MODULE_ENABLED
+  #include "stm32wbxx_hal_tsc.h"
+#endif /* HAL_TSC_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32wbxx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32wbxx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32wbxx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param expr If expr is false, it calls assert_failed function
+  *         which reports the name of the source file and the source
+  *         line number of the call that failed.
+  *         If expr is true, it returns no value.
+  * @retval None
+  */
+  #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+  void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32WBxx_HAL_CONF_H */

+ 2422 - 0
lib/adc/inc/stm32wbxx_hal_tim.h

@@ -0,0 +1,2422 @@
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_tim.h
+  * @author  MCD Application Team
+  * @brief   Header file of TIM HAL module.
+  ******************************************************************************
+  * @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.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32WBxx_HAL_TIM_H
+#define STM32WBxx_HAL_TIM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal_def.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup TIM
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup TIM_Exported_Types TIM Exported Types
+  * @{
+  */
+
+/**
+  * @brief  TIM Time base Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
+                                   This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+
+  uint32_t CounterMode;       /*!< Specifies the counter mode.
+                                   This parameter can be a value of @ref TIM_Counter_Mode */
+
+  uint32_t Period;            /*!< Specifies the period value to be loaded into the active
+                                   Auto-Reload Register at the next update event.
+                                   This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF.  */
+
+  uint32_t ClockDivision;     /*!< Specifies the clock division.
+                                   This parameter can be a value of @ref TIM_ClockDivision */
+
+  uint32_t RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
+                                    reaches zero, an update event is generated and counting restarts
+                                    from the RCR value (N).
+                                    This means in PWM mode that (N+1) corresponds to:
+                                        - the number of PWM periods in edge-aligned mode
+                                        - the number of half PWM period in center-aligned mode
+                                     GP timers: this parameter must be a number between Min_Data = 0x00 and
+                                     Max_Data = 0xFF.
+                                     Advanced timers: this parameter must be a number between Min_Data = 0x0000 and
+                                     Max_Data = 0xFFFF. */
+
+  uint32_t AutoReloadPreload;  /*!< Specifies the auto-reload preload.
+                                   This parameter can be a value of @ref TIM_AutoReloadPreload */
+} TIM_Base_InitTypeDef;
+
+/**
+  * @brief  TIM Output Compare Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t OCMode;        /*!< Specifies the TIM mode.
+                               This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
+
+  uint32_t Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
+                               This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+
+  uint32_t OCPolarity;    /*!< Specifies the output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_Polarity */
+
+  uint32_t OCNPolarity;   /*!< Specifies the complementary output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCFastMode;    /*!< Specifies the Fast mode state.
+                               This parameter can be a value of @ref TIM_Output_Fast_State
+                               @note This parameter is valid only in PWM1 and PWM2 mode. */
+
+
+  uint32_t OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+} TIM_OC_InitTypeDef;
+
+/**
+  * @brief  TIM One Pulse Mode Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t OCMode;        /*!< Specifies the TIM mode.
+                               This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
+
+  uint32_t Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
+                               This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
+
+  uint32_t OCPolarity;    /*!< Specifies the output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_Polarity */
+
+  uint32_t OCNPolarity;   /*!< Specifies the complementary output polarity.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
+                               This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
+                               @note This parameter is valid only for timer instances supporting break feature. */
+
+  uint32_t ICPolarity;    /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Input_Capture_Polarity */
+
+  uint32_t ICSelection;   /*!< Specifies the input.
+                              This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t ICFilter;      /*!< Specifies the input capture filter.
+                              This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_OnePulse_InitTypeDef;
+
+/**
+  * @brief  TIM Input Capture Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t  ICPolarity;  /*!< Specifies the active edge of the input signal.
+                              This parameter can be a value of @ref TIM_Input_Capture_Polarity */
+
+  uint32_t ICSelection;  /*!< Specifies the input.
+                              This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
+                              This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t ICFilter;     /*!< Specifies the input capture filter.
+                              This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_IC_InitTypeDef;
+
+/**
+  * @brief  TIM Encoder Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t EncoderMode;   /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Encoder_Mode */
+
+  uint32_t IC1Polarity;   /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Encoder_Input_Polarity */
+
+  uint32_t IC1Selection;  /*!< Specifies the input.
+                               This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t IC1Prescaler;  /*!< Specifies the Input Capture Prescaler.
+                               This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t IC1Filter;     /*!< Specifies the input capture filter.
+                               This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+
+  uint32_t IC2Polarity;   /*!< Specifies the active edge of the input signal.
+                               This parameter can be a value of @ref TIM_Encoder_Input_Polarity */
+
+  uint32_t IC2Selection;  /*!< Specifies the input.
+                              This parameter can be a value of @ref TIM_Input_Capture_Selection */
+
+  uint32_t IC2Prescaler;  /*!< Specifies the Input Capture Prescaler.
+                               This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
+
+  uint32_t IC2Filter;     /*!< Specifies the input capture filter.
+                               This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_Encoder_InitTypeDef;
+
+/**
+  * @brief  Clock Configuration Handle Structure definition
+  */
+typedef struct
+{
+  uint32_t ClockSource;     /*!< TIM clock sources
+                                 This parameter can be a value of @ref TIM_Clock_Source */
+  uint32_t ClockPolarity;   /*!< TIM clock polarity
+                                 This parameter can be a value of @ref TIM_Clock_Polarity */
+  uint32_t ClockPrescaler;  /*!< TIM clock prescaler
+                                 This parameter can be a value of @ref TIM_Clock_Prescaler */
+  uint32_t ClockFilter;     /*!< TIM clock filter
+                                 This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_ClockConfigTypeDef;
+
+/**
+  * @brief  TIM Clear Input Configuration Handle Structure definition
+  */
+typedef struct
+{
+  uint32_t ClearInputState;      /*!< TIM clear Input state
+                                      This parameter can be ENABLE or DISABLE */
+  uint32_t ClearInputSource;     /*!< TIM clear Input sources
+                                      This parameter can be a value of @ref TIM_ClearInput_Source */
+  uint32_t ClearInputPolarity;   /*!< TIM Clear Input polarity
+                                      This parameter can be a value of @ref TIM_ClearInput_Polarity */
+  uint32_t ClearInputPrescaler;  /*!< TIM Clear Input prescaler
+                                      This parameter must be 0: When OCRef clear feature is used with ETR source,
+                                      ETR prescaler must be off */
+  uint32_t ClearInputFilter;     /*!< TIM Clear Input filter
+                                      This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+} TIM_ClearInputConfigTypeDef;
+
+/**
+  * @brief  TIM Master configuration Structure definition
+  * @note   Advanced timers provide TRGO2 internal line which is redirected
+  *         to the ADC
+  */
+typedef struct
+{
+  uint32_t  MasterOutputTrigger;   /*!< Trigger output (TRGO) selection
+                                        This parameter can be a value of @ref TIM_Master_Mode_Selection */
+  uint32_t  MasterOutputTrigger2;  /*!< Trigger output2 (TRGO2) selection
+                                        This parameter can be a value of @ref TIM_Master_Mode_Selection_2 */
+  uint32_t  MasterSlaveMode;       /*!< Master/slave mode selection
+                                        This parameter can be a value of @ref TIM_Master_Slave_Mode
+                                        @note When the Master/slave mode is enabled, the effect of
+                                        an event on the trigger input (TRGI) is delayed to allow a
+                                        perfect synchronization between the current timer and its
+                                        slaves (through TRGO). It is not mandatory in case of timer
+                                        synchronization mode. */
+} TIM_MasterConfigTypeDef;
+
+/**
+  * @brief  TIM Slave configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t  SlaveMode;         /*!< Slave mode selection
+                                    This parameter can be a value of @ref TIM_Slave_Mode */
+  uint32_t  InputTrigger;      /*!< Input Trigger source
+                                    This parameter can be a value of @ref TIM_Trigger_Selection */
+  uint32_t  TriggerPolarity;   /*!< Input Trigger polarity
+                                    This parameter can be a value of @ref TIM_Trigger_Polarity */
+  uint32_t  TriggerPrescaler;  /*!< Input trigger prescaler
+                                    This parameter can be a value of @ref TIM_Trigger_Prescaler */
+  uint32_t  TriggerFilter;     /*!< Input trigger filter
+                                    This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF  */
+
+} TIM_SlaveConfigTypeDef;
+
+/**
+  * @brief  TIM Break input(s) and Dead time configuration Structure definition
+  * @note   2 break inputs can be configured (BKIN and BKIN2) with configurable
+  *        filter and polarity.
+  */
+typedef struct
+{
+  uint32_t OffStateRunMode;      /*!< TIM off state in run mode, This parameter can be a value of @ref TIM_OSSR_Off_State_Selection_for_Run_mode_state */
+
+  uint32_t OffStateIDLEMode;     /*!< TIM off state in IDLE mode, This parameter can be a value of @ref TIM_OSSI_Off_State_Selection_for_Idle_mode_state */
+
+  uint32_t LockLevel;            /*!< TIM Lock level, This parameter can be a value of @ref TIM_Lock_level */
+
+  uint32_t DeadTime;             /*!< TIM dead Time, This parameter can be a number between Min_Data = 0x00 and Max_Data = 0xFF */
+
+  uint32_t BreakState;           /*!< TIM Break State, This parameter can be a value of @ref TIM_Break_Input_enable_disable */
+
+  uint32_t BreakPolarity;        /*!< TIM Break input polarity, This parameter can be a value of @ref TIM_Break_Polarity */
+
+  uint32_t BreakFilter;          /*!< Specifies the break input filter.This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+
+  uint32_t BreakAFMode;          /*!< Specifies the alternate function mode of the break input.This parameter can be a value of @ref TIM_Break_Input_AF_Mode */
+
+  uint32_t Break2State;          /*!< TIM Break2 State, This parameter can be a value of @ref TIM_Break2_Input_enable_disable */
+
+  uint32_t Break2Polarity;       /*!< TIM Break2 input polarity, This parameter can be a value of @ref TIM_Break2_Polarity */
+
+  uint32_t Break2Filter;         /*!< TIM break2 input filter.This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
+
+  uint32_t Break2AFMode;         /*!< Specifies the alternate function mode of the break2 input.This parameter can be a value of @ref TIM_Break2_Input_AF_Mode */
+
+  uint32_t AutomaticOutput;      /*!< TIM Automatic Output Enable state, This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */
+
+} TIM_BreakDeadTimeConfigTypeDef;
+
+/**
+  * @brief  HAL State structures definition
+  */
+typedef enum
+{
+  HAL_TIM_STATE_RESET             = 0x00U,    /*!< Peripheral not yet initialized or disabled  */
+  HAL_TIM_STATE_READY             = 0x01U,    /*!< Peripheral Initialized and ready for use    */
+  HAL_TIM_STATE_BUSY              = 0x02U,    /*!< An internal process is ongoing              */
+  HAL_TIM_STATE_TIMEOUT           = 0x03U,    /*!< Timeout state                               */
+  HAL_TIM_STATE_ERROR             = 0x04U     /*!< Reception process is ongoing                */
+} HAL_TIM_StateTypeDef;
+
+/**
+  * @brief  TIM Channel States definition
+  */
+typedef enum
+{
+  HAL_TIM_CHANNEL_STATE_RESET             = 0x00U,    /*!< TIM Channel initial state                         */
+  HAL_TIM_CHANNEL_STATE_READY             = 0x01U,    /*!< TIM Channel ready for use                         */
+  HAL_TIM_CHANNEL_STATE_BUSY              = 0x02U,    /*!< An internal process is ongoing on the TIM channel */
+} HAL_TIM_ChannelStateTypeDef;
+
+/**
+  * @brief  DMA Burst States definition
+  */
+typedef enum
+{
+  HAL_DMA_BURST_STATE_RESET             = 0x00U,    /*!< DMA Burst initial state */
+  HAL_DMA_BURST_STATE_READY             = 0x01U,    /*!< DMA Burst ready for use */
+  HAL_DMA_BURST_STATE_BUSY              = 0x02U,    /*!< Ongoing DMA Burst       */
+} HAL_TIM_DMABurstStateTypeDef;
+
+/**
+  * @brief  HAL Active channel structures definition
+  */
+typedef enum
+{
+  HAL_TIM_ACTIVE_CHANNEL_1        = 0x01U,    /*!< The active channel is 1     */
+  HAL_TIM_ACTIVE_CHANNEL_2        = 0x02U,    /*!< The active channel is 2     */
+  HAL_TIM_ACTIVE_CHANNEL_3        = 0x04U,    /*!< The active channel is 3     */
+  HAL_TIM_ACTIVE_CHANNEL_4        = 0x08U,    /*!< The active channel is 4     */
+  HAL_TIM_ACTIVE_CHANNEL_5        = 0x10U,    /*!< The active channel is 5     */
+  HAL_TIM_ACTIVE_CHANNEL_6        = 0x20U,    /*!< The active channel is 6     */
+  HAL_TIM_ACTIVE_CHANNEL_CLEARED  = 0x00U     /*!< All active channels cleared */
+} HAL_TIM_ActiveChannel;
+
+/**
+  * @brief  TIM Time Base Handle Structure definition
+  */
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+typedef struct __TIM_HandleTypeDef
+#else
+typedef struct
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+{
+  TIM_TypeDef                        *Instance;         /*!< Register base address                             */
+  TIM_Base_InitTypeDef               Init;              /*!< TIM Time Base required parameters                 */
+  HAL_TIM_ActiveChannel              Channel;           /*!< Active channel                                    */
+  DMA_HandleTypeDef                  *hdma[7];          /*!< DMA Handlers array
+                                                             This array is accessed by a @ref DMA_Handle_index */
+  HAL_LockTypeDef                    Lock;              /*!< Locking object                                    */
+  __IO HAL_TIM_StateTypeDef          State;             /*!< TIM operation state                               */
+  __IO HAL_TIM_ChannelStateTypeDef   ChannelState[6];   /*!< TIM channel operation state                       */
+  __IO HAL_TIM_ChannelStateTypeDef   ChannelNState[4];  /*!< TIM complementary channel operation state         */
+  __IO HAL_TIM_DMABurstStateTypeDef  DMABurstState;     /*!< DMA burst operation state                         */
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  void (* Base_MspInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM Base Msp Init Callback                              */
+  void (* Base_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);            /*!< TIM Base Msp DeInit Callback                            */
+  void (* IC_MspInitCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM IC Msp Init Callback                                */
+  void (* IC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM IC Msp DeInit Callback                              */
+  void (* OC_MspInitCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM OC Msp Init Callback                                */
+  void (* OC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM OC Msp DeInit Callback                              */
+  void (* PWM_MspInitCallback)(struct __TIM_HandleTypeDef *htim);               /*!< TIM PWM Msp Init Callback                               */
+  void (* PWM_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);             /*!< TIM PWM Msp DeInit Callback                             */
+  void (* OnePulse_MspInitCallback)(struct __TIM_HandleTypeDef *htim);          /*!< TIM One Pulse Msp Init Callback                         */
+  void (* OnePulse_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM One Pulse Msp DeInit Callback                       */
+  void (* Encoder_MspInitCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Encoder Msp Init Callback                           */
+  void (* Encoder_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);         /*!< TIM Encoder Msp DeInit Callback                         */
+  void (* HallSensor_MspInitCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM Hall Sensor Msp Init Callback                       */
+  void (* HallSensor_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);      /*!< TIM Hall Sensor Msp DeInit Callback                     */
+  void (* PeriodElapsedCallback)(struct __TIM_HandleTypeDef *htim);             /*!< TIM Period Elapsed Callback                             */
+  void (* PeriodElapsedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);     /*!< TIM Period Elapsed half complete Callback               */
+  void (* TriggerCallback)(struct __TIM_HandleTypeDef *htim);                   /*!< TIM Trigger Callback                                    */
+  void (* TriggerHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Trigger half complete Callback                      */
+  void (* IC_CaptureCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM Input Capture Callback                              */
+  void (* IC_CaptureHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM Input Capture half complete Callback                */
+  void (* OC_DelayElapsedCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Output Compare Delay Elapsed Callback               */
+  void (* PWM_PulseFinishedCallback)(struct __TIM_HandleTypeDef *htim);         /*!< TIM PWM Pulse Finished Callback                         */
+  void (* PWM_PulseFinishedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Pulse Finished half complete Callback           */
+  void (* ErrorCallback)(struct __TIM_HandleTypeDef *htim);                     /*!< TIM Error Callback                                      */
+  void (* CommutationCallback)(struct __TIM_HandleTypeDef *htim);               /*!< TIM Commutation Callback                                */
+  void (* CommutationHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);       /*!< TIM Commutation half complete Callback                  */
+  void (* BreakCallback)(struct __TIM_HandleTypeDef *htim);                     /*!< TIM Break Callback                                      */
+  void (* Break2Callback)(struct __TIM_HandleTypeDef *htim);                    /*!< TIM Break2 Callback                                     */
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+} TIM_HandleTypeDef;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  HAL TIM Callback ID enumeration definition
+  */
+typedef enum
+{
+  HAL_TIM_BASE_MSPINIT_CB_ID              = 0x00U   /*!< TIM Base MspInit Callback ID                              */
+  , HAL_TIM_BASE_MSPDEINIT_CB_ID          = 0x01U   /*!< TIM Base MspDeInit Callback ID                            */
+  , HAL_TIM_IC_MSPINIT_CB_ID              = 0x02U   /*!< TIM IC MspInit Callback ID                                */
+  , HAL_TIM_IC_MSPDEINIT_CB_ID            = 0x03U   /*!< TIM IC MspDeInit Callback ID                              */
+  , HAL_TIM_OC_MSPINIT_CB_ID              = 0x04U   /*!< TIM OC MspInit Callback ID                                */
+  , HAL_TIM_OC_MSPDEINIT_CB_ID            = 0x05U   /*!< TIM OC MspDeInit Callback ID                              */
+  , HAL_TIM_PWM_MSPINIT_CB_ID             = 0x06U   /*!< TIM PWM MspInit Callback ID                               */
+  , HAL_TIM_PWM_MSPDEINIT_CB_ID           = 0x07U   /*!< TIM PWM MspDeInit Callback ID                             */
+  , HAL_TIM_ONE_PULSE_MSPINIT_CB_ID       = 0x08U   /*!< TIM One Pulse MspInit Callback ID                         */
+  , HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID     = 0x09U   /*!< TIM One Pulse MspDeInit Callback ID                       */
+  , HAL_TIM_ENCODER_MSPINIT_CB_ID         = 0x0AU   /*!< TIM Encoder MspInit Callback ID                           */
+  , HAL_TIM_ENCODER_MSPDEINIT_CB_ID       = 0x0BU   /*!< TIM Encoder MspDeInit Callback ID                         */
+  , HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID     = 0x0CU   /*!< TIM Hall Sensor MspDeInit Callback ID                     */
+  , HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID   = 0x0DU   /*!< TIM Hall Sensor MspDeInit Callback ID                     */
+  , HAL_TIM_PERIOD_ELAPSED_CB_ID          = 0x0EU   /*!< TIM Period Elapsed Callback ID                             */
+  , HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID     = 0x0FU   /*!< TIM Period Elapsed half complete Callback ID               */
+  , HAL_TIM_TRIGGER_CB_ID                 = 0x10U   /*!< TIM Trigger Callback ID                                    */
+  , HAL_TIM_TRIGGER_HALF_CB_ID            = 0x11U   /*!< TIM Trigger half complete Callback ID                      */
+
+  , HAL_TIM_IC_CAPTURE_CB_ID              = 0x12U   /*!< TIM Input Capture Callback ID                              */
+  , HAL_TIM_IC_CAPTURE_HALF_CB_ID         = 0x13U   /*!< TIM Input Capture half complete Callback ID                */
+  , HAL_TIM_OC_DELAY_ELAPSED_CB_ID        = 0x14U   /*!< TIM Output Compare Delay Elapsed Callback ID               */
+  , HAL_TIM_PWM_PULSE_FINISHED_CB_ID      = 0x15U   /*!< TIM PWM Pulse Finished Callback ID           */
+  , HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID = 0x16U   /*!< TIM PWM Pulse Finished half complete Callback ID           */
+  , HAL_TIM_ERROR_CB_ID                   = 0x17U   /*!< TIM Error Callback ID                                      */
+  , HAL_TIM_COMMUTATION_CB_ID             = 0x18U   /*!< TIM Commutation Callback ID                                */
+  , HAL_TIM_COMMUTATION_HALF_CB_ID        = 0x19U   /*!< TIM Commutation half complete Callback ID                  */
+  , HAL_TIM_BREAK_CB_ID                   = 0x1AU   /*!< TIM Break Callback ID                                      */
+  , HAL_TIM_BREAK2_CB_ID                  = 0x1BU   /*!< TIM Break2 Callback ID                                     */
+} HAL_TIM_CallbackIDTypeDef;
+
+/**
+  * @brief  HAL TIM Callback pointer definition
+  */
+typedef  void (*pTIM_CallbackTypeDef)(TIM_HandleTypeDef *htim);  /*!< pointer to the TIM callback function */
+
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+/* End of exported types -----------------------------------------------------*/
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup TIM_Exported_Constants TIM Exported Constants
+  * @{
+  */
+
+/** @defgroup TIM_ClearInput_Source TIM Clear Input Source
+  * @{
+  */
+#define TIM_CLEARINPUTSOURCE_NONE           0x00000000U         /*!< OCREF_CLR is disabled */
+#define TIM_CLEARINPUTSOURCE_ETR            0x00000001U         /*!< OCREF_CLR is connected to ETRF input */
+#define TIM_CLEARINPUTSOURCE_COMP1          TIM1_AF1_ETRSEL_0   /*!< OCREF_CLR_INT is connected to COMP1 output */
+#define TIM_CLEARINPUTSOURCE_COMP2          TIM1_AF1_ETRSEL_1   /*!< OCREF_CLR_INT is connected to COMP2 output */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_DMA_Base_address TIM DMA Base Address
+  * @{
+  */
+#define TIM_DMABASE_CR1                    0x00000000U
+#define TIM_DMABASE_CR2                    0x00000001U
+#define TIM_DMABASE_SMCR                   0x00000002U
+#define TIM_DMABASE_DIER                   0x00000003U
+#define TIM_DMABASE_SR                     0x00000004U
+#define TIM_DMABASE_EGR                    0x00000005U
+#define TIM_DMABASE_CCMR1                  0x00000006U
+#define TIM_DMABASE_CCMR2                  0x00000007U
+#define TIM_DMABASE_CCER                   0x00000008U
+#define TIM_DMABASE_CNT                    0x00000009U
+#define TIM_DMABASE_PSC                    0x0000000AU
+#define TIM_DMABASE_ARR                    0x0000000BU
+#define TIM_DMABASE_RCR                    0x0000000CU
+#define TIM_DMABASE_CCR1                   0x0000000DU
+#define TIM_DMABASE_CCR2                   0x0000000EU
+#define TIM_DMABASE_CCR3                   0x0000000FU
+#define TIM_DMABASE_CCR4                   0x00000010U
+#define TIM_DMABASE_BDTR                   0x00000011U
+#define TIM_DMABASE_DCR                    0x00000012U
+#define TIM_DMABASE_DMAR                   0x00000013U
+#define TIM_DMABASE_OR                     0x00000014U
+#define TIM_DMABASE_CCMR3                  0x00000015U
+#define TIM_DMABASE_CCR5                   0x00000016U
+#define TIM_DMABASE_CCR6                   0x00000017U
+#define TIM_DMABASE_AF1                    0x00000018U
+#define TIM_DMABASE_AF2                    0x00000019U
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Event_Source TIM Event Source
+  * @{
+  */
+#define TIM_EVENTSOURCE_UPDATE              TIM_EGR_UG     /*!< Reinitialize the counter and generates an update of the registers */
+#define TIM_EVENTSOURCE_CC1                 TIM_EGR_CC1G   /*!< A capture/compare event is generated on channel 1 */
+#define TIM_EVENTSOURCE_CC2                 TIM_EGR_CC2G   /*!< A capture/compare event is generated on channel 2 */
+#define TIM_EVENTSOURCE_CC3                 TIM_EGR_CC3G   /*!< A capture/compare event is generated on channel 3 */
+#define TIM_EVENTSOURCE_CC4                 TIM_EGR_CC4G   /*!< A capture/compare event is generated on channel 4 */
+#define TIM_EVENTSOURCE_COM                 TIM_EGR_COMG   /*!< A commutation event is generated */
+#define TIM_EVENTSOURCE_TRIGGER             TIM_EGR_TG     /*!< A trigger event is generated */
+#define TIM_EVENTSOURCE_BREAK               TIM_EGR_BG     /*!< A break event is generated */
+#define TIM_EVENTSOURCE_BREAK2              TIM_EGR_B2G    /*!< A break 2 event is generated */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Channel_Polarity TIM Input Channel polarity
+  * @{
+  */
+#define  TIM_INPUTCHANNELPOLARITY_RISING      0x00000000U                       /*!< Polarity for TIx source */
+#define  TIM_INPUTCHANNELPOLARITY_FALLING     TIM_CCER_CC1P                     /*!< Polarity for TIx source */
+#define  TIM_INPUTCHANNELPOLARITY_BOTHEDGE    (TIM_CCER_CC1P | TIM_CCER_CC1NP)  /*!< Polarity for TIx source */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ETR_Polarity TIM ETR Polarity
+  * @{
+  */
+#define TIM_ETRPOLARITY_INVERTED              TIM_SMCR_ETP                      /*!< Polarity for ETR source */
+#define TIM_ETRPOLARITY_NONINVERTED           0x00000000U                       /*!< Polarity for ETR source */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ETR_Prescaler TIM ETR Prescaler
+  * @{
+  */
+#define TIM_ETRPRESCALER_DIV1                 0x00000000U                       /*!< No prescaler is used */
+#define TIM_ETRPRESCALER_DIV2                 TIM_SMCR_ETPS_0                   /*!< ETR input source is divided by 2 */
+#define TIM_ETRPRESCALER_DIV4                 TIM_SMCR_ETPS_1                   /*!< ETR input source is divided by 4 */
+#define TIM_ETRPRESCALER_DIV8                 TIM_SMCR_ETPS                     /*!< ETR input source is divided by 8 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Counter_Mode TIM Counter Mode
+  * @{
+  */
+#define TIM_COUNTERMODE_UP                 0x00000000U                          /*!< Counter used as up-counter   */
+#define TIM_COUNTERMODE_DOWN               TIM_CR1_DIR                          /*!< Counter used as down-counter */
+#define TIM_COUNTERMODE_CENTERALIGNED1     TIM_CR1_CMS_0                        /*!< Center-aligned mode 1        */
+#define TIM_COUNTERMODE_CENTERALIGNED2     TIM_CR1_CMS_1                        /*!< Center-aligned mode 2        */
+#define TIM_COUNTERMODE_CENTERALIGNED3     TIM_CR1_CMS                          /*!< Center-aligned mode 3        */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Update_Interrupt_Flag_Remap TIM Update Interrupt Flag Remap
+  * @{
+  */
+#define TIM_UIFREMAP_DISABLE               0x00000000U                          /*!< Update interrupt flag remap disabled */
+#define TIM_UIFREMAP_ENABLE                TIM_CR1_UIFREMAP                     /*!< Update interrupt flag remap enabled */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ClockDivision TIM Clock Division
+  * @{
+  */
+#define TIM_CLOCKDIVISION_DIV1             0x00000000U                          /*!< Clock division: tDTS=tCK_INT   */
+#define TIM_CLOCKDIVISION_DIV2             TIM_CR1_CKD_0                        /*!< Clock division: tDTS=2*tCK_INT */
+#define TIM_CLOCKDIVISION_DIV4             TIM_CR1_CKD_1                        /*!< Clock division: tDTS=4*tCK_INT */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_State TIM Output Compare State
+  * @{
+  */
+#define TIM_OUTPUTSTATE_DISABLE            0x00000000U                          /*!< Capture/Compare 1 output disabled */
+#define TIM_OUTPUTSTATE_ENABLE             TIM_CCER_CC1E                        /*!< Capture/Compare 1 output enabled */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_AutoReloadPreload TIM Auto-Reload Preload
+  * @{
+  */
+#define TIM_AUTORELOAD_PRELOAD_DISABLE                0x00000000U               /*!< TIMx_ARR register is not buffered */
+#define TIM_AUTORELOAD_PRELOAD_ENABLE                 TIM_CR1_ARPE              /*!< TIMx_ARR register is buffered */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Fast_State TIM Output Fast State
+  * @{
+  */
+#define TIM_OCFAST_DISABLE                 0x00000000U                          /*!< Output Compare fast disable */
+#define TIM_OCFAST_ENABLE                  TIM_CCMR1_OC1FE                      /*!< Output Compare fast enable  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_N_State TIM Complementary Output Compare State
+  * @{
+  */
+#define TIM_OUTPUTNSTATE_DISABLE           0x00000000U                          /*!< OCxN is disabled  */
+#define TIM_OUTPUTNSTATE_ENABLE            TIM_CCER_CC1NE                       /*!< OCxN is enabled   */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_Polarity TIM Output Compare Polarity
+  * @{
+  */
+#define TIM_OCPOLARITY_HIGH                0x00000000U                          /*!< Capture/Compare output polarity  */
+#define TIM_OCPOLARITY_LOW                 TIM_CCER_CC1P                        /*!< Capture/Compare output polarity  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_N_Polarity TIM Complementary Output Compare Polarity
+  * @{
+  */
+#define TIM_OCNPOLARITY_HIGH               0x00000000U                          /*!< Capture/Compare complementary output polarity */
+#define TIM_OCNPOLARITY_LOW                TIM_CCER_CC1NP                       /*!< Capture/Compare complementary output polarity */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_Idle_State TIM Output Compare Idle State
+  * @{
+  */
+#define TIM_OCIDLESTATE_SET                TIM_CR2_OIS1                         /*!< Output Idle state: OCx=1 when MOE=0 */
+#define TIM_OCIDLESTATE_RESET              0x00000000U                          /*!< Output Idle state: OCx=0 when MOE=0 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_N_Idle_State TIM Complementary Output Compare Idle State
+  * @{
+  */
+#define TIM_OCNIDLESTATE_SET               TIM_CR2_OIS1N                        /*!< Complementary output Idle state: OCxN=1 when MOE=0 */
+#define TIM_OCNIDLESTATE_RESET             0x00000000U                          /*!< Complementary output Idle state: OCxN=0 when MOE=0 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Capture_Polarity TIM Input Capture Polarity
+  * @{
+  */
+#define  TIM_ICPOLARITY_RISING             TIM_INPUTCHANNELPOLARITY_RISING      /*!< Capture triggered by rising edge on timer input                  */
+#define  TIM_ICPOLARITY_FALLING            TIM_INPUTCHANNELPOLARITY_FALLING     /*!< Capture triggered by falling edge on timer input                 */
+#define  TIM_ICPOLARITY_BOTHEDGE           TIM_INPUTCHANNELPOLARITY_BOTHEDGE    /*!< Capture triggered by both rising and falling edges on timer input*/
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Encoder_Input_Polarity TIM Encoder Input Polarity
+  * @{
+  */
+#define  TIM_ENCODERINPUTPOLARITY_RISING   TIM_INPUTCHANNELPOLARITY_RISING      /*!< Encoder input with rising edge polarity  */
+#define  TIM_ENCODERINPUTPOLARITY_FALLING  TIM_INPUTCHANNELPOLARITY_FALLING     /*!< Encoder input with falling edge polarity */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Capture_Selection TIM Input Capture Selection
+  * @{
+  */
+#define TIM_ICSELECTION_DIRECTTI           TIM_CCMR1_CC1S_0                     /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to IC1, IC2, IC3 or IC4, respectively */
+#define TIM_ICSELECTION_INDIRECTTI         TIM_CCMR1_CC1S_1                     /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to IC2, IC1, IC4 or IC3, respectively */
+#define TIM_ICSELECTION_TRC                TIM_CCMR1_CC1S                       /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Input_Capture_Prescaler TIM Input Capture Prescaler
+  * @{
+  */
+#define TIM_ICPSC_DIV1                     0x00000000U                          /*!< Capture performed each time an edge is detected on the capture input */
+#define TIM_ICPSC_DIV2                     TIM_CCMR1_IC1PSC_0                   /*!< Capture performed once every 2 events                                */
+#define TIM_ICPSC_DIV4                     TIM_CCMR1_IC1PSC_1                   /*!< Capture performed once every 4 events                                */
+#define TIM_ICPSC_DIV8                     TIM_CCMR1_IC1PSC                     /*!< Capture performed once every 8 events                                */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_One_Pulse_Mode TIM One Pulse Mode
+  * @{
+  */
+#define TIM_OPMODE_SINGLE                  TIM_CR1_OPM                          /*!< Counter stops counting at the next update event */
+#define TIM_OPMODE_REPETITIVE              0x00000000U                          /*!< Counter is not stopped at update event          */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Encoder_Mode TIM Encoder Mode
+  * @{
+  */
+#define TIM_ENCODERMODE_TI1                      TIM_SMCR_SMS_0                                                      /*!< Quadrature encoder mode 1, x2 mode, counts up/down on TI1FP1 edge depending on TI2FP2 level  */
+#define TIM_ENCODERMODE_TI2                      TIM_SMCR_SMS_1                                                      /*!< Quadrature encoder mode 2, x2 mode, counts up/down on TI2FP2 edge depending on TI1FP1 level. */
+#define TIM_ENCODERMODE_TI12                     (TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0)                                   /*!< Quadrature encoder mode 3, x4 mode, counts up/down on both TI1FP1 and TI2FP2 edges depending on the level of the other input. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Interrupt_definition TIM interrupt Definition
+  * @{
+  */
+#define TIM_IT_UPDATE                      TIM_DIER_UIE                         /*!< Update interrupt            */
+#define TIM_IT_CC1                         TIM_DIER_CC1IE                       /*!< Capture/Compare 1 interrupt */
+#define TIM_IT_CC2                         TIM_DIER_CC2IE                       /*!< Capture/Compare 2 interrupt */
+#define TIM_IT_CC3                         TIM_DIER_CC3IE                       /*!< Capture/Compare 3 interrupt */
+#define TIM_IT_CC4                         TIM_DIER_CC4IE                       /*!< Capture/Compare 4 interrupt */
+#define TIM_IT_COM                         TIM_DIER_COMIE                       /*!< Commutation interrupt       */
+#define TIM_IT_TRIGGER                     TIM_DIER_TIE                         /*!< Trigger interrupt           */
+#define TIM_IT_BREAK                       TIM_DIER_BIE                         /*!< Break interrupt             */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Commutation_Source  TIM Commutation Source
+  * @{
+  */
+#define TIM_COMMUTATION_TRGI              TIM_CR2_CCUS                          /*!< When Capture/compare control bits are preloaded, they are updated by setting the COMG bit or when an rising edge occurs on trigger input */
+#define TIM_COMMUTATION_SOFTWARE          0x00000000U                           /*!< When Capture/compare control bits are preloaded, they are updated by setting the COMG bit */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_DMA_sources TIM DMA Sources
+  * @{
+  */
+#define TIM_DMA_UPDATE                     TIM_DIER_UDE                         /*!< DMA request is triggered by the update event */
+#define TIM_DMA_CC1                        TIM_DIER_CC1DE                       /*!< DMA request is triggered by the capture/compare macth 1 event */
+#define TIM_DMA_CC2                        TIM_DIER_CC2DE                       /*!< DMA request is triggered by the capture/compare macth 2 event event */
+#define TIM_DMA_CC3                        TIM_DIER_CC3DE                       /*!< DMA request is triggered by the capture/compare macth 3 event event */
+#define TIM_DMA_CC4                        TIM_DIER_CC4DE                       /*!< DMA request is triggered by the capture/compare macth 4 event event */
+#define TIM_DMA_COM                        TIM_DIER_COMDE                       /*!< DMA request is triggered by the commutation event */
+#define TIM_DMA_TRIGGER                    TIM_DIER_TDE                         /*!< DMA request is triggered by the trigger event */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_CC_DMA_Request CCx DMA request selection
+  * @{
+  */
+#define TIM_CCDMAREQUEST_CC                 0x00000000U                         /*!< CCx DMA request sent when capture or compare match event occurs */
+#define TIM_CCDMAREQUEST_UPDATE             TIM_CR2_CCDS                        /*!< CCx DMA requests sent when update event occurs */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Flag_definition TIM Flag Definition
+  * @{
+  */
+#define TIM_FLAG_UPDATE                    TIM_SR_UIF                           /*!< Update interrupt flag         */
+#define TIM_FLAG_CC1                       TIM_SR_CC1IF                         /*!< Capture/Compare 1 interrupt flag */
+#define TIM_FLAG_CC2                       TIM_SR_CC2IF                         /*!< Capture/Compare 2 interrupt flag */
+#define TIM_FLAG_CC3                       TIM_SR_CC3IF                         /*!< Capture/Compare 3 interrupt flag */
+#define TIM_FLAG_CC4                       TIM_SR_CC4IF                         /*!< Capture/Compare 4 interrupt flag */
+#define TIM_FLAG_CC5                       TIM_SR_CC5IF                         /*!< Capture/Compare 5 interrupt flag */
+#define TIM_FLAG_CC6                       TIM_SR_CC6IF                         /*!< Capture/Compare 6 interrupt flag */
+#define TIM_FLAG_COM                       TIM_SR_COMIF                         /*!< Commutation interrupt flag    */
+#define TIM_FLAG_TRIGGER                   TIM_SR_TIF                           /*!< Trigger interrupt flag        */
+#define TIM_FLAG_BREAK                     TIM_SR_BIF                           /*!< Break interrupt flag          */
+#define TIM_FLAG_BREAK2                    TIM_SR_B2IF                          /*!< Break 2 interrupt flag        */
+#define TIM_FLAG_SYSTEM_BREAK              TIM_SR_SBIF                          /*!< System Break interrupt flag   */
+#define TIM_FLAG_CC1OF                     TIM_SR_CC1OF                         /*!< Capture 1 overcapture flag    */
+#define TIM_FLAG_CC2OF                     TIM_SR_CC2OF                         /*!< Capture 2 overcapture flag    */
+#define TIM_FLAG_CC3OF                     TIM_SR_CC3OF                         /*!< Capture 3 overcapture flag    */
+#define TIM_FLAG_CC4OF                     TIM_SR_CC4OF                         /*!< Capture 4 overcapture flag    */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Channel TIM Channel
+  * @{
+  */
+#define TIM_CHANNEL_1                      0x00000000U                          /*!< Capture/compare channel 1 identifier      */
+#define TIM_CHANNEL_2                      0x00000004U                          /*!< Capture/compare channel 2 identifier      */
+#define TIM_CHANNEL_3                      0x00000008U                          /*!< Capture/compare channel 3 identifier      */
+#define TIM_CHANNEL_4                      0x0000000CU                          /*!< Capture/compare channel 4 identifier      */
+#define TIM_CHANNEL_5                      0x00000010U                          /*!< Compare channel 5 identifier              */
+#define TIM_CHANNEL_6                      0x00000014U                          /*!< Compare channel 6 identifier              */
+#define TIM_CHANNEL_ALL                    0x0000003CU                          /*!< Global Capture/compare channel identifier  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Source TIM Clock Source
+  * @{
+  */
+#define TIM_CLOCKSOURCE_INTERNAL    TIM_SMCR_ETPS_0      /*!< Internal clock source                                 */
+#define TIM_CLOCKSOURCE_ETRMODE1    TIM_TS_ETRF          /*!< External clock source mode 1 (ETRF)                   */
+#define TIM_CLOCKSOURCE_ETRMODE2    TIM_SMCR_ETPS_1      /*!< External clock source mode 2                          */
+#define TIM_CLOCKSOURCE_TI1ED       TIM_TS_TI1F_ED       /*!< External clock source mode 1 (TTI1FP1 + edge detect.) */
+#define TIM_CLOCKSOURCE_TI1         TIM_TS_TI1FP1        /*!< External clock source mode 1 (TTI1FP1)                */
+#define TIM_CLOCKSOURCE_TI2         TIM_TS_TI2FP2        /*!< External clock source mode 1 (TTI2FP2)                */
+#define TIM_CLOCKSOURCE_ITR0        TIM_TS_ITR0          /*!< External clock source mode 1 (ITR0)                   */
+#define TIM_CLOCKSOURCE_ITR1        TIM_TS_ITR1          /*!< External clock source mode 1 (ITR1)                   */
+#define TIM_CLOCKSOURCE_ITR2        TIM_TS_ITR2          /*!< External clock source mode 1 (ITR2)                   */
+#define TIM_CLOCKSOURCE_ITR3        TIM_TS_ITR3          /*!< External clock source mode 1 (ITR3)                   */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Polarity TIM Clock Polarity
+  * @{
+  */
+#define TIM_CLOCKPOLARITY_INVERTED           TIM_ETRPOLARITY_INVERTED           /*!< Polarity for ETRx clock sources */
+#define TIM_CLOCKPOLARITY_NONINVERTED        TIM_ETRPOLARITY_NONINVERTED        /*!< Polarity for ETRx clock sources */
+#define TIM_CLOCKPOLARITY_RISING             TIM_INPUTCHANNELPOLARITY_RISING    /*!< Polarity for TIx clock sources */
+#define TIM_CLOCKPOLARITY_FALLING            TIM_INPUTCHANNELPOLARITY_FALLING   /*!< Polarity for TIx clock sources */
+#define TIM_CLOCKPOLARITY_BOTHEDGE           TIM_INPUTCHANNELPOLARITY_BOTHEDGE  /*!< Polarity for TIx clock sources */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Prescaler TIM Clock Prescaler
+  * @{
+  */
+#define TIM_CLOCKPRESCALER_DIV1                 TIM_ETRPRESCALER_DIV1           /*!< No prescaler is used                                                     */
+#define TIM_CLOCKPRESCALER_DIV2                 TIM_ETRPRESCALER_DIV2           /*!< Prescaler for External ETR Clock: Capture performed once every 2 events. */
+#define TIM_CLOCKPRESCALER_DIV4                 TIM_ETRPRESCALER_DIV4           /*!< Prescaler for External ETR Clock: Capture performed once every 4 events. */
+#define TIM_CLOCKPRESCALER_DIV8                 TIM_ETRPRESCALER_DIV8           /*!< Prescaler for External ETR Clock: Capture performed once every 8 events. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ClearInput_Polarity TIM Clear Input Polarity
+  * @{
+  */
+#define TIM_CLEARINPUTPOLARITY_INVERTED           TIM_ETRPOLARITY_INVERTED      /*!< Polarity for ETRx pin */
+#define TIM_CLEARINPUTPOLARITY_NONINVERTED        TIM_ETRPOLARITY_NONINVERTED   /*!< Polarity for ETRx pin */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_ClearInput_Prescaler TIM Clear Input Prescaler
+  * @{
+  */
+#define TIM_CLEARINPUTPRESCALER_DIV1              TIM_ETRPRESCALER_DIV1         /*!< No prescaler is used                                                   */
+#define TIM_CLEARINPUTPRESCALER_DIV2              TIM_ETRPRESCALER_DIV2         /*!< Prescaler for External ETR pin: Capture performed once every 2 events. */
+#define TIM_CLEARINPUTPRESCALER_DIV4              TIM_ETRPRESCALER_DIV4         /*!< Prescaler for External ETR pin: Capture performed once every 4 events. */
+#define TIM_CLEARINPUTPRESCALER_DIV8              TIM_ETRPRESCALER_DIV8         /*!< Prescaler for External ETR pin: Capture performed once every 8 events. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_OSSR_Off_State_Selection_for_Run_mode_state TIM OSSR OffState Selection for Run mode state
+  * @{
+  */
+#define TIM_OSSR_ENABLE                          TIM_BDTR_OSSR                  /*!< When inactive, OC/OCN outputs are enabled (still controlled by the timer)           */
+#define TIM_OSSR_DISABLE                         0x00000000U                    /*!< When inactive, OC/OCN outputs are disabled (not controlled any longer by the timer) */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_OSSI_Off_State_Selection_for_Idle_mode_state TIM OSSI OffState Selection for Idle mode state
+  * @{
+  */
+#define TIM_OSSI_ENABLE                          TIM_BDTR_OSSI                  /*!< When inactive, OC/OCN outputs are enabled (still controlled by the timer)           */
+#define TIM_OSSI_DISABLE                         0x00000000U                    /*!< When inactive, OC/OCN outputs are disabled (not controlled any longer by the timer) */
+/**
+  * @}
+  */
+/** @defgroup TIM_Lock_level  TIM Lock level
+  * @{
+  */
+#define TIM_LOCKLEVEL_OFF                  0x00000000U                          /*!< LOCK OFF     */
+#define TIM_LOCKLEVEL_1                    TIM_BDTR_LOCK_0                      /*!< LOCK Level 1 */
+#define TIM_LOCKLEVEL_2                    TIM_BDTR_LOCK_1                      /*!< LOCK Level 2 */
+#define TIM_LOCKLEVEL_3                    TIM_BDTR_LOCK                        /*!< LOCK Level 3 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break_Input_enable_disable TIM Break Input Enable
+  * @{
+  */
+#define TIM_BREAK_ENABLE                   TIM_BDTR_BKE                         /*!< Break input BRK is enabled  */
+#define TIM_BREAK_DISABLE                  0x00000000U                          /*!< Break input BRK is disabled */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break_Polarity TIM Break Input Polarity
+  * @{
+  */
+#define TIM_BREAKPOLARITY_LOW              0x00000000U                          /*!< Break input BRK is active low  */
+#define TIM_BREAKPOLARITY_HIGH             TIM_BDTR_BKP                         /*!< Break input BRK is active high */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break_Input_AF_Mode TIM Break Input Alternate Function Mode
+  * @{
+  */
+#define TIM_BREAK_AFMODE_INPUT             0x00000000U                          /*!< Break input BRK in input mode */
+#define TIM_BREAK_AFMODE_BIDIRECTIONAL     TIM_BDTR_BKBID                       /*!< Break input BRK in bidirectional mode */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break2_Input_enable_disable TIM Break input 2 Enable
+  * @{
+  */
+#define TIM_BREAK2_DISABLE                 0x00000000U                          /*!< Break input BRK2 is disabled  */
+#define TIM_BREAK2_ENABLE                  TIM_BDTR_BK2E                        /*!< Break input BRK2 is enabled  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break2_Polarity TIM Break Input 2 Polarity
+  * @{
+  */
+#define TIM_BREAK2POLARITY_LOW             0x00000000U                          /*!< Break input BRK2 is active low   */
+#define TIM_BREAK2POLARITY_HIGH            TIM_BDTR_BK2P                        /*!< Break input BRK2 is active high  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break2_Input_AF_Mode TIM Break2 Input Alternate Function Mode
+  * @{
+  */
+#define TIM_BREAK2_AFMODE_INPUT            0x00000000U                          /*!< Break2 input BRK2 in input mode */
+#define TIM_BREAK2_AFMODE_BIDIRECTIONAL    TIM_BDTR_BK2BID                      /*!< Break2 input BRK2 in bidirectional mode */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_AOE_Bit_Set_Reset TIM Automatic Output Enable
+  * @{
+  */
+#define TIM_AUTOMATICOUTPUT_DISABLE        0x00000000U                          /*!< MOE can be set only by software */
+#define TIM_AUTOMATICOUTPUT_ENABLE         TIM_BDTR_AOE                         /*!< MOE can be set by software or automatically at the next update event (if none of the break inputs BRK and BRK2 is active) */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Group_Channel5 TIM Group Channel 5 and Channel 1, 2 or 3
+  * @{
+  */
+#define TIM_GROUPCH5_NONE                  0x00000000U                          /*!< No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC */
+#define TIM_GROUPCH5_OC1REFC               TIM_CCR5_GC5C1                       /*!< OC1REFC is the logical AND of OC1REFC and OC5REF    */
+#define TIM_GROUPCH5_OC2REFC               TIM_CCR5_GC5C2                       /*!< OC2REFC is the logical AND of OC2REFC and OC5REF    */
+#define TIM_GROUPCH5_OC3REFC               TIM_CCR5_GC5C3                       /*!< OC3REFC is the logical AND of OC3REFC and OC5REF    */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Master_Mode_Selection TIM Master Mode Selection
+  * @{
+  */
+#define TIM_TRGO_RESET            0x00000000U                                      /*!< TIMx_EGR.UG bit is used as trigger output (TRGO)              */
+#define TIM_TRGO_ENABLE           TIM_CR2_MMS_0                                    /*!< TIMx_CR1.CEN bit is used as trigger output (TRGO)             */
+#define TIM_TRGO_UPDATE           TIM_CR2_MMS_1                                    /*!< Update event is used as trigger output (TRGO)                 */
+#define TIM_TRGO_OC1              (TIM_CR2_MMS_1 | TIM_CR2_MMS_0)                  /*!< Capture or a compare match 1 is used as trigger output (TRGO) */
+#define TIM_TRGO_OC1REF           TIM_CR2_MMS_2                                    /*!< OC1REF signal is used as trigger output (TRGO)                */
+#define TIM_TRGO_OC2REF           (TIM_CR2_MMS_2 | TIM_CR2_MMS_0)                  /*!< OC2REF signal is used as trigger output(TRGO)                 */
+#define TIM_TRGO_OC3REF           (TIM_CR2_MMS_2 | TIM_CR2_MMS_1)                  /*!< OC3REF signal is used as trigger output(TRGO)                 */
+#define TIM_TRGO_OC4REF           (TIM_CR2_MMS_2 | TIM_CR2_MMS_1 | TIM_CR2_MMS_0)  /*!< OC4REF signal is used as trigger output(TRGO)                 */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Master_Mode_Selection_2 TIM Master Mode Selection 2 (TRGO2)
+  * @{
+  */
+#define TIM_TRGO2_RESET                          0x00000000U                                                         /*!< TIMx_EGR.UG bit is used as trigger output (TRGO2)              */
+#define TIM_TRGO2_ENABLE                         TIM_CR2_MMS2_0                                                      /*!< TIMx_CR1.CEN bit is used as trigger output (TRGO2)             */
+#define TIM_TRGO2_UPDATE                         TIM_CR2_MMS2_1                                                      /*!< Update event is used as trigger output (TRGO2)                 */
+#define TIM_TRGO2_OC1                            (TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)                                   /*!< Capture or a compare match 1 is used as trigger output (TRGO2) */
+#define TIM_TRGO2_OC1REF                         TIM_CR2_MMS2_2                                                      /*!< OC1REF signal is used as trigger output (TRGO2)                */
+#define TIM_TRGO2_OC2REF                         (TIM_CR2_MMS2_2 | TIM_CR2_MMS2_0)                                   /*!< OC2REF signal is used as trigger output (TRGO2)                */
+#define TIM_TRGO2_OC3REF                         (TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1)                                   /*!< OC3REF signal is used as trigger output (TRGO2)                */
+#define TIM_TRGO2_OC4REF                         (TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)                  /*!< OC4REF signal is used as trigger output (TRGO2)                */
+#define TIM_TRGO2_OC5REF                         TIM_CR2_MMS2_3                                                      /*!< OC5REF signal is used as trigger output (TRGO2)                */
+#define TIM_TRGO2_OC6REF                         (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_0)                                   /*!< OC6REF signal is used as trigger output (TRGO2)                */
+#define TIM_TRGO2_OC4REF_RISINGFALLING           (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_1)                                   /*!< OC4REF rising or falling edges generate pulses on TRGO2        */
+#define TIM_TRGO2_OC6REF_RISINGFALLING           (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)                  /*!< OC6REF rising or falling edges generate pulses on TRGO2        */
+#define TIM_TRGO2_OC4REF_RISING_OC6REF_RISING    (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2)                                   /*!< OC4REF or OC6REF rising edges generate pulses on TRGO2         */
+#define TIM_TRGO2_OC4REF_RISING_OC6REF_FALLING   (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | TIM_CR2_MMS2_0)                  /*!< OC4REF rising or OC6REF falling edges generate pulses on TRGO2 */
+#define TIM_TRGO2_OC5REF_RISING_OC6REF_RISING    (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 |TIM_CR2_MMS2_1)                   /*!< OC5REF or OC6REF rising edges generate pulses on TRGO2         */
+#define TIM_TRGO2_OC5REF_RISING_OC6REF_FALLING   (TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0) /*!< OC5REF or OC6REF rising edges generate pulses on TRGO2         */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Master_Slave_Mode TIM Master/Slave Mode
+  * @{
+  */
+#define TIM_MASTERSLAVEMODE_ENABLE         TIM_SMCR_MSM                         /*!< No action */
+#define TIM_MASTERSLAVEMODE_DISABLE        0x00000000U                          /*!< Master/slave mode is selected */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Slave_Mode TIM Slave mode
+  * @{
+  */
+#define TIM_SLAVEMODE_DISABLE                0x00000000U                                        /*!< Slave mode disabled           */
+#define TIM_SLAVEMODE_RESET                  TIM_SMCR_SMS_2                                     /*!< Reset Mode                    */
+#define TIM_SLAVEMODE_GATED                  (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0)                  /*!< Gated Mode                    */
+#define TIM_SLAVEMODE_TRIGGER                (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1)                  /*!< Trigger Mode                  */
+#define TIM_SLAVEMODE_EXTERNAL1              (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0) /*!< External Clock Mode 1         */
+#define TIM_SLAVEMODE_COMBINED_RESETTRIGGER  TIM_SMCR_SMS_3                                     /*!< Combined reset + trigger mode */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_and_PWM_modes TIM Output Compare and PWM Modes
+  * @{
+  */
+#define TIM_OCMODE_TIMING                   0x00000000U                                              /*!< Frozen                                 */
+#define TIM_OCMODE_ACTIVE                   TIM_CCMR1_OC1M_0                                         /*!< Set channel to active level on match   */
+#define TIM_OCMODE_INACTIVE                 TIM_CCMR1_OC1M_1                                         /*!< Set channel to inactive level on match */
+#define TIM_OCMODE_TOGGLE                   (TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0)                    /*!< Toggle                                 */
+#define TIM_OCMODE_PWM1                     (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1)                    /*!< PWM mode 1                             */
+#define TIM_OCMODE_PWM2                     (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) /*!< PWM mode 2                             */
+#define TIM_OCMODE_FORCED_ACTIVE            (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0)                    /*!< Force active level                     */
+#define TIM_OCMODE_FORCED_INACTIVE          TIM_CCMR1_OC1M_2                                         /*!< Force inactive level                   */
+#define TIM_OCMODE_RETRIGERRABLE_OPM1      TIM_CCMR1_OC1M_3                                          /*!< Retrigerrable OPM mode 1               */
+#define TIM_OCMODE_RETRIGERRABLE_OPM2      (TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_0)                     /*!< Retrigerrable OPM mode 2               */
+#define TIM_OCMODE_COMBINED_PWM1           (TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_2)                     /*!< Combined PWM mode 1                    */
+#define TIM_OCMODE_COMBINED_PWM2           (TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_2)  /*!< Combined PWM mode 2                    */
+#define TIM_OCMODE_ASSYMETRIC_PWM1         (TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2)  /*!< Asymmetric PWM mode 1                  */
+#define TIM_OCMODE_ASSYMETRIC_PWM2         TIM_CCMR1_OC1M                                            /*!< Asymmetric PWM mode 2                  */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Trigger_Selection TIM Trigger Selection
+  * @{
+  */
+#define TIM_TS_ITR0          0x00000000U                                                       /*!< Internal Trigger 0 (ITR0)              */
+#define TIM_TS_ITR1          TIM_SMCR_TS_0                                                     /*!< Internal Trigger 1 (ITR1)              */
+#define TIM_TS_ITR2          TIM_SMCR_TS_1                                                     /*!< Internal Trigger 2 (ITR2)              */
+#define TIM_TS_ITR3          (TIM_SMCR_TS_0 | TIM_SMCR_TS_1)                                   /*!< Internal Trigger 3 (ITR3)              */
+#define TIM_TS_TI1F_ED       TIM_SMCR_TS_2                                                     /*!< TI1 Edge Detector (TI1F_ED)            */
+#define TIM_TS_TI1FP1        (TIM_SMCR_TS_0 | TIM_SMCR_TS_2)                                   /*!< Filtered Timer Input 1 (TI1FP1)        */
+#define TIM_TS_TI2FP2        (TIM_SMCR_TS_1 | TIM_SMCR_TS_2)                                   /*!< Filtered Timer Input 2 (TI2FP2)        */
+#define TIM_TS_ETRF          (TIM_SMCR_TS_0 | TIM_SMCR_TS_1 | TIM_SMCR_TS_2)                   /*!< Filtered External Trigger input (ETRF) */
+#define TIM_TS_NONE          0x0000FFFFU                                                       /*!< No trigger selected                    */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Trigger_Polarity TIM Trigger Polarity
+  * @{
+  */
+#define TIM_TRIGGERPOLARITY_INVERTED           TIM_ETRPOLARITY_INVERTED               /*!< Polarity for ETRx trigger sources             */
+#define TIM_TRIGGERPOLARITY_NONINVERTED        TIM_ETRPOLARITY_NONINVERTED            /*!< Polarity for ETRx trigger sources             */
+#define TIM_TRIGGERPOLARITY_RISING             TIM_INPUTCHANNELPOLARITY_RISING        /*!< Polarity for TIxFPx or TI1_ED trigger sources */
+#define TIM_TRIGGERPOLARITY_FALLING            TIM_INPUTCHANNELPOLARITY_FALLING       /*!< Polarity for TIxFPx or TI1_ED trigger sources */
+#define TIM_TRIGGERPOLARITY_BOTHEDGE           TIM_INPUTCHANNELPOLARITY_BOTHEDGE      /*!< Polarity for TIxFPx or TI1_ED trigger sources */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Trigger_Prescaler TIM Trigger Prescaler
+  * @{
+  */
+#define TIM_TRIGGERPRESCALER_DIV1             TIM_ETRPRESCALER_DIV1             /*!< No prescaler is used                                                       */
+#define TIM_TRIGGERPRESCALER_DIV2             TIM_ETRPRESCALER_DIV2             /*!< Prescaler for External ETR Trigger: Capture performed once every 2 events. */
+#define TIM_TRIGGERPRESCALER_DIV4             TIM_ETRPRESCALER_DIV4             /*!< Prescaler for External ETR Trigger: Capture performed once every 4 events. */
+#define TIM_TRIGGERPRESCALER_DIV8             TIM_ETRPRESCALER_DIV8             /*!< Prescaler for External ETR Trigger: Capture performed once every 8 events. */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_TI1_Selection TIM TI1 Input Selection
+  * @{
+  */
+#define TIM_TI1SELECTION_CH1               0x00000000U                          /*!< The TIMx_CH1 pin is connected to TI1 input */
+#define TIM_TI1SELECTION_XORCOMBINATION    TIM_CR2_TI1S                         /*!< The TIMx_CH1, CH2 and CH3 pins are connected to the TI1 input (XOR combination) */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_DMA_Burst_Length TIM DMA Burst Length
+  * @{
+  */
+#define TIM_DMABURSTLENGTH_1TRANSFER       0x00000000U                          /*!< The transfer is done to 1 register starting from TIMx_CR1 + TIMx_DCR.DBA   */
+#define TIM_DMABURSTLENGTH_2TRANSFERS      0x00000100U                          /*!< The transfer is done to 2 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_3TRANSFERS      0x00000200U                          /*!< The transfer is done to 3 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_4TRANSFERS      0x00000300U                          /*!< The transfer is done to 4 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_5TRANSFERS      0x00000400U                          /*!< The transfer is done to 5 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_6TRANSFERS      0x00000500U                          /*!< The transfer is done to 6 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_7TRANSFERS      0x00000600U                          /*!< The transfer is done to 7 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_8TRANSFERS      0x00000700U                          /*!< The transfer is done to 8 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_9TRANSFERS      0x00000800U                          /*!< The transfer is done to 9 registers starting from TIMx_CR1 + TIMx_DCR.DBA  */
+#define TIM_DMABURSTLENGTH_10TRANSFERS     0x00000900U                          /*!< The transfer is done to 10 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_11TRANSFERS     0x00000A00U                          /*!< The transfer is done to 11 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_12TRANSFERS     0x00000B00U                          /*!< The transfer is done to 12 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_13TRANSFERS     0x00000C00U                          /*!< The transfer is done to 13 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_14TRANSFERS     0x00000D00U                          /*!< The transfer is done to 14 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_15TRANSFERS     0x00000E00U                          /*!< The transfer is done to 15 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_16TRANSFERS     0x00000F00U                          /*!< The transfer is done to 16 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_17TRANSFERS     0x00001000U                          /*!< The transfer is done to 17 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+#define TIM_DMABURSTLENGTH_18TRANSFERS     0x00001100U                          /*!< The transfer is done to 18 registers starting from TIMx_CR1 + TIMx_DCR.DBA */
+/**
+  * @}
+  */
+
+/** @defgroup DMA_Handle_index TIM DMA Handle Index
+  * @{
+  */
+#define TIM_DMA_ID_UPDATE                ((uint16_t) 0x0000)       /*!< Index of the DMA handle used for Update DMA requests */
+#define TIM_DMA_ID_CC1                   ((uint16_t) 0x0001)       /*!< Index of the DMA handle used for Capture/Compare 1 DMA requests */
+#define TIM_DMA_ID_CC2                   ((uint16_t) 0x0002)       /*!< Index of the DMA handle used for Capture/Compare 2 DMA requests */
+#define TIM_DMA_ID_CC3                   ((uint16_t) 0x0003)       /*!< Index of the DMA handle used for Capture/Compare 3 DMA requests */
+#define TIM_DMA_ID_CC4                   ((uint16_t) 0x0004)       /*!< Index of the DMA handle used for Capture/Compare 4 DMA requests */
+#define TIM_DMA_ID_COMMUTATION           ((uint16_t) 0x0005)       /*!< Index of the DMA handle used for Commutation DMA requests */
+#define TIM_DMA_ID_TRIGGER               ((uint16_t) 0x0006)       /*!< Index of the DMA handle used for Trigger DMA requests */
+/**
+  * @}
+  */
+
+/** @defgroup Channel_CC_State TIM Capture/Compare Channel State
+  * @{
+  */
+#define TIM_CCx_ENABLE                   0x00000001U                            /*!< Input or output channel is enabled */
+#define TIM_CCx_DISABLE                  0x00000000U                            /*!< Input or output channel is disabled */
+#define TIM_CCxN_ENABLE                  0x00000004U                            /*!< Complementary output channel is enabled */
+#define TIM_CCxN_DISABLE                 0x00000000U                            /*!< Complementary output channel is enabled */
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Break_System TIM Break System
+  * @{
+  */
+#define TIM_BREAK_SYSTEM_ECC                 SYSCFG_CFGR2_ECCL   /*!< Enables and locks the ECC error signal with Break Input of TIM1/8/15/16/17 */
+#define TIM_BREAK_SYSTEM_PVD                 SYSCFG_CFGR2_PVDL   /*!< Enables and locks the PVD connection with TIM1/8/15/16/17 Break Input and also the PVDE and PLS bits of the Power Control Interface */
+#define TIM_BREAK_SYSTEM_SRAM2_PARITY_ERROR  SYSCFG_CFGR2_SPL    /*!< Enables and locks the SRAM2_PARITY error signal with Break Input of TIM1/8/15/16/17 */
+#define TIM_BREAK_SYSTEM_LOCKUP              SYSCFG_CFGR2_CLL    /*!< Enables and locks the LOCKUP output of CortexM4 with Break Input of TIM1/8/15/16/17 */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/* End of exported constants -------------------------------------------------*/
+
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup TIM_Exported_Macros TIM Exported Macros
+  * @{
+  */
+
+/** @brief  Reset TIM handle state.
+  * @param  __HANDLE__ TIM handle.
+  * @retval None
+  */
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+#define __HAL_TIM_RESET_HANDLE_STATE(__HANDLE__) do {                                                               \
+                                                      (__HANDLE__)->State            = HAL_TIM_STATE_RESET;         \
+                                                      (__HANDLE__)->ChannelState[0]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[1]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[2]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[3]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[4]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[5]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[0] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[1] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[2] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[3] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->DMABurstState    = HAL_DMA_BURST_STATE_RESET;   \
+                                                      (__HANDLE__)->Base_MspInitCallback         = NULL;            \
+                                                      (__HANDLE__)->Base_MspDeInitCallback       = NULL;            \
+                                                      (__HANDLE__)->IC_MspInitCallback           = NULL;            \
+                                                      (__HANDLE__)->IC_MspDeInitCallback         = NULL;            \
+                                                      (__HANDLE__)->OC_MspInitCallback           = NULL;            \
+                                                      (__HANDLE__)->OC_MspDeInitCallback         = NULL;            \
+                                                      (__HANDLE__)->PWM_MspInitCallback          = NULL;            \
+                                                      (__HANDLE__)->PWM_MspDeInitCallback        = NULL;            \
+                                                      (__HANDLE__)->OnePulse_MspInitCallback     = NULL;            \
+                                                      (__HANDLE__)->OnePulse_MspDeInitCallback   = NULL;            \
+                                                      (__HANDLE__)->Encoder_MspInitCallback      = NULL;            \
+                                                      (__HANDLE__)->Encoder_MspDeInitCallback    = NULL;            \
+                                                      (__HANDLE__)->HallSensor_MspInitCallback   = NULL;            \
+                                                      (__HANDLE__)->HallSensor_MspDeInitCallback = NULL;            \
+                                                     } while(0)
+#else
+#define __HAL_TIM_RESET_HANDLE_STATE(__HANDLE__) do {                                                               \
+                                                      (__HANDLE__)->State            = HAL_TIM_STATE_RESET;         \
+                                                      (__HANDLE__)->ChannelState[0]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[1]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[2]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[3]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[4]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelState[5]  = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[0] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[1] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[2] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->ChannelNState[3] = HAL_TIM_CHANNEL_STATE_RESET; \
+                                                      (__HANDLE__)->DMABurstState    = HAL_DMA_BURST_STATE_RESET;   \
+                                                     } while(0)
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @brief  Enable the TIM peripheral.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE(__HANDLE__)                 ((__HANDLE__)->Instance->CR1|=(TIM_CR1_CEN))
+
+/**
+  * @brief  Enable the TIM main Output.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  */
+#define __HAL_TIM_MOE_ENABLE(__HANDLE__)             ((__HANDLE__)->Instance->BDTR|=(TIM_BDTR_MOE))
+
+/**
+  * @brief  Disable the TIM peripheral.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE(__HANDLE__) \
+  do { \
+    if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0UL) \
+    { \
+      if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0UL) \
+      { \
+        (__HANDLE__)->Instance->CR1 &= ~(TIM_CR1_CEN); \
+      } \
+    } \
+  } while(0)
+
+/**
+  * @brief  Disable the TIM main Output.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  * @note The Main Output Enable of a timer instance is disabled only if all the CCx and CCxN channels have been
+  *       disabled
+  */
+#define __HAL_TIM_MOE_DISABLE(__HANDLE__) \
+  do { \
+    if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0UL) \
+    { \
+      if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0UL) \
+      { \
+        (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE); \
+      } \
+    } \
+  } while(0)
+
+/**
+  * @brief  Disable the TIM main Output.
+  * @param  __HANDLE__ TIM handle
+  * @retval None
+  * @note The Main Output Enable of a timer instance is disabled unconditionally
+  */
+#define __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(__HANDLE__)  (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE)
+
+/** @brief  Enable the specified TIM interrupt.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __INTERRUPT__ specifies the TIM interrupt source to enable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__)    ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__))
+
+/** @brief  Disable the specified TIM interrupt.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __INTERRUPT__ specifies the TIM interrupt source to disable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_IT(__HANDLE__, __INTERRUPT__)   ((__HANDLE__)->Instance->DIER &= ~(__INTERRUPT__))
+
+/** @brief  Enable the specified DMA request.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __DMA__ specifies the TIM DMA request to enable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: Update DMA request
+  *            @arg TIM_DMA_CC1:   Capture/Compare 1 DMA request
+  *            @arg TIM_DMA_CC2:  Capture/Compare 2 DMA request
+  *            @arg TIM_DMA_CC3:  Capture/Compare 3 DMA request
+  *            @arg TIM_DMA_CC4:  Capture/Compare 4 DMA request
+  *            @arg TIM_DMA_COM:   Commutation DMA request
+  *            @arg TIM_DMA_TRIGGER: Trigger DMA request
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_DMA(__HANDLE__, __DMA__)         ((__HANDLE__)->Instance->DIER |= (__DMA__))
+
+/** @brief  Disable the specified DMA request.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __DMA__ specifies the TIM DMA request to disable.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: Update DMA request
+  *            @arg TIM_DMA_CC1:   Capture/Compare 1 DMA request
+  *            @arg TIM_DMA_CC2:  Capture/Compare 2 DMA request
+  *            @arg TIM_DMA_CC3:  Capture/Compare 3 DMA request
+  *            @arg TIM_DMA_CC4:  Capture/Compare 4 DMA request
+  *            @arg TIM_DMA_COM:   Commutation DMA request
+  *            @arg TIM_DMA_TRIGGER: Trigger DMA request
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_DMA(__HANDLE__, __DMA__)        ((__HANDLE__)->Instance->DIER &= ~(__DMA__))
+
+/** @brief  Check whether the specified TIM interrupt flag is set or not.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __FLAG__ specifies the TIM interrupt flag to check.
+  *        This parameter can be one of the following values:
+  *            @arg TIM_FLAG_UPDATE: Update interrupt flag
+  *            @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag
+  *            @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag
+  *            @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag
+  *            @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag
+  *            @arg TIM_FLAG_CC5: Compare 5 interrupt flag
+  *            @arg TIM_FLAG_CC6: Compare 6 interrupt flag
+  *            @arg TIM_FLAG_COM:  Commutation interrupt flag
+  *            @arg TIM_FLAG_TRIGGER: Trigger interrupt flag
+  *            @arg TIM_FLAG_BREAK: Break interrupt flag
+  *            @arg TIM_FLAG_BREAK2: Break 2 interrupt flag
+  *            @arg TIM_FLAG_SYSTEM_BREAK: System Break interrupt flag
+  *            @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag
+  *            @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag
+  *            @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag
+  *            @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag
+  * @retval The new state of __FLAG__ (TRUE or FALSE).
+  */
+#define __HAL_TIM_GET_FLAG(__HANDLE__, __FLAG__)          (((__HANDLE__)->Instance->SR &(__FLAG__)) == (__FLAG__))
+
+/** @brief  Clear the specified TIM interrupt flag.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __FLAG__ specifies the TIM interrupt flag to clear.
+  *        This parameter can be one of the following values:
+  *            @arg TIM_FLAG_UPDATE: Update interrupt flag
+  *            @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag
+  *            @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag
+  *            @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag
+  *            @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag
+  *            @arg TIM_FLAG_CC5: Compare 5 interrupt flag
+  *            @arg TIM_FLAG_CC6: Compare 6 interrupt flag
+  *            @arg TIM_FLAG_COM:  Commutation interrupt flag
+  *            @arg TIM_FLAG_TRIGGER: Trigger interrupt flag
+  *            @arg TIM_FLAG_BREAK: Break interrupt flag
+  *            @arg TIM_FLAG_BREAK2: Break 2 interrupt flag
+  *            @arg TIM_FLAG_SYSTEM_BREAK: System Break interrupt flag
+  *            @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag
+  *            @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag
+  *            @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag
+  *            @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag
+  * @retval The new state of __FLAG__ (TRUE or FALSE).
+  */
+#define __HAL_TIM_CLEAR_FLAG(__HANDLE__, __FLAG__)        ((__HANDLE__)->Instance->SR = ~(__FLAG__))
+
+/**
+  * @brief  Check whether the specified TIM interrupt source is enabled or not.
+  * @param  __HANDLE__ TIM handle
+  * @param  __INTERRUPT__ specifies the TIM interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval The state of TIM_IT (SET or RESET).
+  */
+#define __HAL_TIM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->DIER & (__INTERRUPT__)) \
+                                                             == (__INTERRUPT__)) ? SET : RESET)
+
+/** @brief Clear the TIM interrupt pending bits.
+  * @param  __HANDLE__ TIM handle
+  * @param  __INTERRUPT__ specifies the interrupt pending bit to clear.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_IT_UPDATE: Update interrupt
+  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
+  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
+  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
+  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
+  *            @arg TIM_IT_COM:   Commutation interrupt
+  *            @arg TIM_IT_TRIGGER: Trigger interrupt
+  *            @arg TIM_IT_BREAK: Break interrupt
+  * @retval None
+  */
+#define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__)      ((__HANDLE__)->Instance->SR = ~(__INTERRUPT__))
+
+/**
+  * @brief  Force a continuous copy of the update interrupt flag (UIF) into the timer counter register (bit 31).
+  * @note This allows both the counter value and a potential roll-over condition signalled by the UIFCPY flag to be read
+  *       in an atomic way.
+  * @param  __HANDLE__ TIM handle.
+  * @retval None
+mode.
+  */
+#define __HAL_TIM_UIFREMAP_ENABLE(__HANDLE__)    (((__HANDLE__)->Instance->CR1 |= TIM_CR1_UIFREMAP))
+
+/**
+  * @brief  Disable update interrupt flag (UIF) remapping.
+  * @param  __HANDLE__ TIM handle.
+  * @retval None
+mode.
+  */
+#define __HAL_TIM_UIFREMAP_DISABLE(__HANDLE__)    (((__HANDLE__)->Instance->CR1 &= ~TIM_CR1_UIFREMAP))
+
+/**
+  * @brief  Get update interrupt flag (UIF) copy status.
+  * @param  __COUNTER__ Counter value.
+  * @retval The state of UIFCPY (TRUE or FALSE).
+mode.
+  */
+#define __HAL_TIM_GET_UIFCPY(__COUNTER__)    (((__COUNTER__) & (TIM_CNT_UIFCPY)) == (TIM_CNT_UIFCPY))
+
+/**
+  * @brief  Indicates whether or not the TIM Counter is used as downcounter.
+  * @param  __HANDLE__ TIM handle.
+  * @retval False (Counter used as upcounter) or True (Counter used as downcounter)
+  * @note This macro is particularly useful to get the counting mode when the timer operates in Center-aligned mode
+  *       or Encoder mode.
+  */
+#define __HAL_TIM_IS_TIM_COUNTING_DOWN(__HANDLE__)    (((__HANDLE__)->Instance->CR1 &(TIM_CR1_DIR)) == (TIM_CR1_DIR))
+
+/**
+  * @brief  Set the TIM Prescaler on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __PRESC__ specifies the Prescaler new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_PRESCALER(__HANDLE__, __PRESC__)       ((__HANDLE__)->Instance->PSC = (__PRESC__))
+
+/**
+  * @brief  Set the TIM Counter Register value on runtime.
+  * Note Please check if the bit 31 of CNT register is used as UIF copy or not, this may affect the counter range in
+  *      case of 32 bits counter TIM instance.
+  *      Bit 31 of CNT can be enabled/disabled using __HAL_TIM_UIFREMAP_ENABLE()/__HAL_TIM_UIFREMAP_DISABLE() macros.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __COUNTER__ specifies the Counter register new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__)  ((__HANDLE__)->Instance->CNT = (__COUNTER__))
+
+/**
+  * @brief  Get the TIM Counter Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @retval 16-bit or 32-bit value of the timer counter register (TIMx_CNT)
+  */
+#define __HAL_TIM_GET_COUNTER(__HANDLE__)  ((__HANDLE__)->Instance->CNT)
+
+/**
+  * @brief  Set the TIM Autoreload Register value on runtime without calling another time any Init function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __AUTORELOAD__ specifies the Counter register new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__) \
+  do{                                                    \
+    (__HANDLE__)->Instance->ARR = (__AUTORELOAD__);  \
+    (__HANDLE__)->Init.Period = (__AUTORELOAD__);    \
+  } while(0)
+
+/**
+  * @brief  Get the TIM Autoreload Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @retval 16-bit or 32-bit value of the timer auto-reload register(TIMx_ARR)
+  */
+#define __HAL_TIM_GET_AUTORELOAD(__HANDLE__)  ((__HANDLE__)->Instance->ARR)
+
+/**
+  * @brief  Set the TIM Clock Division value on runtime without calling another time any Init function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CKD__ specifies the clock division value.
+  *          This parameter can be one of the following value:
+  *            @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT
+  * @retval None
+  */
+#define __HAL_TIM_SET_CLOCKDIVISION(__HANDLE__, __CKD__) \
+  do{                                                   \
+    (__HANDLE__)->Instance->CR1 &= (~TIM_CR1_CKD);  \
+    (__HANDLE__)->Instance->CR1 |= (__CKD__);       \
+    (__HANDLE__)->Init.ClockDivision = (__CKD__);   \
+  } while(0)
+
+/**
+  * @brief  Get the TIM Clock Division value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @retval The clock division can be one of the following values:
+  *            @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT
+  *            @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT
+  */
+#define __HAL_TIM_GET_CLOCKDIVISION(__HANDLE__)  ((__HANDLE__)->Instance->CR1 & TIM_CR1_CKD)
+
+/**
+  * @brief  Set the TIM Input Capture prescaler on runtime without calling another time HAL_TIM_IC_ConfigChannel()
+  *         function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  __ICPSC__ specifies the Input Capture4 prescaler new value.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPSC_DIV1: no prescaler
+  *            @arg TIM_ICPSC_DIV2: capture is done once every 2 events
+  *            @arg TIM_ICPSC_DIV4: capture is done once every 4 events
+  *            @arg TIM_ICPSC_DIV8: capture is done once every 8 events
+  * @retval None
+  */
+#define __HAL_TIM_SET_ICPRESCALER(__HANDLE__, __CHANNEL__, __ICPSC__) \
+  do{                                                    \
+    TIM_RESET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__));  \
+    TIM_SET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__), (__ICPSC__)); \
+  } while(0)
+
+/**
+  * @brief  Get the TIM Input Capture prescaler on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: get input capture 1 prescaler value
+  *            @arg TIM_CHANNEL_2: get input capture 2 prescaler value
+  *            @arg TIM_CHANNEL_3: get input capture 3 prescaler value
+  *            @arg TIM_CHANNEL_4: get input capture 4 prescaler value
+  * @retval The input capture prescaler can be one of the following values:
+  *            @arg TIM_ICPSC_DIV1: no prescaler
+  *            @arg TIM_ICPSC_DIV2: capture is done once every 2 events
+  *            @arg TIM_ICPSC_DIV4: capture is done once every 4 events
+  *            @arg TIM_ICPSC_DIV8: capture is done once every 8 events
+  */
+#define __HAL_TIM_GET_ICPRESCALER(__HANDLE__, __CHANNEL__)  \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC1PSC) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? (((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC2PSC) >> 8U) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC3PSC) :\
+   (((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC4PSC)) >> 8U)
+
+/**
+  * @brief  Set the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @param  __COMPARE__ specifies the Capture Compare register new value.
+  * @retval None
+  */
+#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5 = (__COMPARE__)) :\
+   ((__HANDLE__)->Instance->CCR6 = (__COMPARE__)))
+
+/**
+  * @brief  Get the TIM Capture Compare Register value on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channel associated with the capture compare register
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: get capture/compare 1 register value
+  *            @arg TIM_CHANNEL_2: get capture/compare 2 register value
+  *            @arg TIM_CHANNEL_3: get capture/compare 3 register value
+  *            @arg TIM_CHANNEL_4: get capture/compare 4 register value
+  *            @arg TIM_CHANNEL_5: get capture/compare 5 register value
+  *            @arg TIM_CHANNEL_6: get capture/compare 6 register value
+  * @retval 16-bit or 32-bit value of the capture/compare register (TIMx_CCRy)
+  */
+#define __HAL_TIM_GET_COMPARE(__HANDLE__, __CHANNEL__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5) :\
+   ((__HANDLE__)->Instance->CCR6))
+
+/**
+  * @brief  Set the TIM Output compare preload.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC1PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC2PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC3PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC4PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC5PE) :\
+   ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC6PE))
+
+/**
+  * @brief  Reset the TIM Output compare preload.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC1PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC2PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC3PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC4PE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 &= ~TIM_CCMR3_OC5PE) :\
+   ((__HANDLE__)->Instance->CCMR3 &= ~TIM_CCMR3_OC6PE))
+
+/**
+  * @brief  Enable fast mode for a given channel.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @note  When fast mode is enabled an active edge on the trigger input acts
+  *        like a compare match on CCx output. Delay to sample the trigger
+  *        input and to activate CCx output is reduced to 3 clock cycles.
+  * @note  Fast mode acts only if the channel is configured in PWM1 or PWM2 mode.
+  * @retval None
+  */
+#define __HAL_TIM_ENABLE_OCxFAST(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC1FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC2FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC3FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC4FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC5FE) :\
+   ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC6FE))
+
+/**
+  * @brief  Disable fast mode for a given channel.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @note  When fast mode is disabled CCx output behaves normally depending
+  *        on counter and CCRx values even when the trigger is ON. The minimum
+  *        delay to activate CCx output when an active edge occurs on the
+  *        trigger input is 5 clock cycles.
+  * @retval None
+  */
+#define __HAL_TIM_DISABLE_OCxFAST(__HANDLE__, __CHANNEL__)    \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 &= ~TIM_CCMR3_OC5FE) :\
+   ((__HANDLE__)->Instance->CCMR3 &= ~TIM_CCMR3_OC6FE))
+
+/**
+  * @brief  Set the Update Request Source (URS) bit of the TIMx_CR1 register.
+  * @param  __HANDLE__ TIM handle.
+  * @note  When the URS bit of the TIMx_CR1 register is set, only counter
+  *        overflow/underflow generates an update interrupt or DMA request (if
+  *        enabled)
+  * @retval None
+  */
+#define __HAL_TIM_URS_ENABLE(__HANDLE__)  ((__HANDLE__)->Instance->CR1|= TIM_CR1_URS)
+
+/**
+  * @brief  Reset the Update Request Source (URS) bit of the TIMx_CR1 register.
+  * @param  __HANDLE__ TIM handle.
+  * @note  When the URS bit of the TIMx_CR1 register is reset, any of the
+  *        following events generate an update interrupt or DMA request (if
+  *        enabled):
+  *           _ Counter overflow underflow
+  *           _ Setting the UG bit
+  *           _ Update generation through the slave mode controller
+  * @retval None
+  */
+#define __HAL_TIM_URS_DISABLE(__HANDLE__)  ((__HANDLE__)->Instance->CR1&=~TIM_CR1_URS)
+
+/**
+  * @brief  Set the TIM Capture x input polarity on runtime.
+  * @param  __HANDLE__ TIM handle.
+  * @param  __CHANNEL__ TIM Channels to be configured.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  __POLARITY__ Polarity for TIx source
+  *            @arg TIM_INPUTCHANNELPOLARITY_RISING: Rising Edge
+  *            @arg TIM_INPUTCHANNELPOLARITY_FALLING: Falling Edge
+  *            @arg TIM_INPUTCHANNELPOLARITY_BOTHEDGE: Rising and Falling Edge
+  * @retval None
+  */
+#define __HAL_TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__)    \
+  do{                                                                     \
+    TIM_RESET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__));               \
+    TIM_SET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__), (__POLARITY__)); \
+  }while(0)
+
+/** @brief  Select the Capture/compare DMA request source.
+  * @param  __HANDLE__ specifies the TIM Handle.
+  * @param  __CCDMA__ specifies Capture/compare DMA request source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CCDMAREQUEST_CC: CCx DMA request generated on Capture/Compare event
+  *            @arg TIM_CCDMAREQUEST_UPDATE: CCx DMA request generated on Update event
+  * @retval None
+  */
+#define __HAL_TIM_SELECT_CCDMAREQUEST(__HANDLE__, __CCDMA__)    \
+  MODIFY_REG((__HANDLE__)->Instance->CR2, TIM_CR2_CCDS, (__CCDMA__))
+
+/**
+  * @}
+  */
+/* End of exported macros ----------------------------------------------------*/
+
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup TIM_Private_Constants TIM Private Constants
+  * @{
+  */
+/* The counter of a timer instance is disabled only if all the CCx and CCxN
+   channels have been disabled */
+#define TIM_CCER_CCxE_MASK  ((uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E))
+#define TIM_CCER_CCxNE_MASK ((uint32_t)(TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE))
+/**
+  * @}
+  */
+/* End of private constants --------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup TIM_Private_Macros TIM Private Macros
+  * @{
+  */
+#define IS_TIM_CLEARINPUT_SOURCE(__MODE__)  (((__MODE__) == TIM_CLEARINPUTSOURCE_ETR)      || \
+                                             ((__MODE__) == TIM_CLEARINPUTSOURCE_COMP1)    || \
+                                             ((__MODE__) == TIM_CLEARINPUTSOURCE_COMP2)    || \
+                                             ((__MODE__) == TIM_CLEARINPUTSOURCE_NONE))
+
+#define IS_TIM_DMA_BASE(__BASE__) (((__BASE__) == TIM_DMABASE_CR1)    || \
+                                   ((__BASE__) == TIM_DMABASE_CR2)    || \
+                                   ((__BASE__) == TIM_DMABASE_SMCR)   || \
+                                   ((__BASE__) == TIM_DMABASE_DIER)   || \
+                                   ((__BASE__) == TIM_DMABASE_SR)     || \
+                                   ((__BASE__) == TIM_DMABASE_EGR)    || \
+                                   ((__BASE__) == TIM_DMABASE_CCMR1)  || \
+                                   ((__BASE__) == TIM_DMABASE_CCMR2)  || \
+                                   ((__BASE__) == TIM_DMABASE_CCER)   || \
+                                   ((__BASE__) == TIM_DMABASE_CNT)    || \
+                                   ((__BASE__) == TIM_DMABASE_PSC)    || \
+                                   ((__BASE__) == TIM_DMABASE_ARR)    || \
+                                   ((__BASE__) == TIM_DMABASE_RCR)    || \
+                                   ((__BASE__) == TIM_DMABASE_CCR1)   || \
+                                   ((__BASE__) == TIM_DMABASE_CCR2)   || \
+                                   ((__BASE__) == TIM_DMABASE_CCR3)   || \
+                                   ((__BASE__) == TIM_DMABASE_CCR4)   || \
+                                   ((__BASE__) == TIM_DMABASE_BDTR)   || \
+                                   ((__BASE__) == TIM_DMABASE_OR)     || \
+                                   ((__BASE__) == TIM_DMABASE_CCMR3)  || \
+                                   ((__BASE__) == TIM_DMABASE_CCR5)   || \
+                                   ((__BASE__) == TIM_DMABASE_CCR6)   || \
+                                   ((__BASE__) == TIM_DMABASE_AF1)    || \
+                                   ((__BASE__) == TIM_DMABASE_AF2))
+
+#define IS_TIM_EVENT_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFFFE00U) == 0x00000000U) && ((__SOURCE__) != 0x00000000U))
+
+#define IS_TIM_COUNTER_MODE(__MODE__)      (((__MODE__) == TIM_COUNTERMODE_UP)              || \
+                                            ((__MODE__) == TIM_COUNTERMODE_DOWN)            || \
+                                            ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED1)  || \
+                                            ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED2)  || \
+                                            ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED3))
+
+#define IS_TIM_UIFREMAP_MODE(__MODE__)     (((__MODE__) == TIM_UIFREMAP_DISABLE) || \
+                                            ((__MODE__) == TIM_UIFREMAP_ENABLE))
+
+#define IS_TIM_CLOCKDIVISION_DIV(__DIV__)  (((__DIV__) == TIM_CLOCKDIVISION_DIV1) || \
+                                            ((__DIV__) == TIM_CLOCKDIVISION_DIV2) || \
+                                            ((__DIV__) == TIM_CLOCKDIVISION_DIV4))
+
+#define IS_TIM_AUTORELOAD_PRELOAD(PRELOAD) (((PRELOAD) == TIM_AUTORELOAD_PRELOAD_DISABLE) || \
+                                            ((PRELOAD) == TIM_AUTORELOAD_PRELOAD_ENABLE))
+
+#define IS_TIM_FAST_STATE(__STATE__)       (((__STATE__) == TIM_OCFAST_DISABLE) || \
+                                            ((__STATE__) == TIM_OCFAST_ENABLE))
+
+#define IS_TIM_OC_POLARITY(__POLARITY__)   (((__POLARITY__) == TIM_OCPOLARITY_HIGH) || \
+                                            ((__POLARITY__) == TIM_OCPOLARITY_LOW))
+
+#define IS_TIM_OCN_POLARITY(__POLARITY__)  (((__POLARITY__) == TIM_OCNPOLARITY_HIGH) || \
+                                            ((__POLARITY__) == TIM_OCNPOLARITY_LOW))
+
+#define IS_TIM_OCIDLE_STATE(__STATE__)     (((__STATE__) == TIM_OCIDLESTATE_SET) || \
+                                            ((__STATE__) == TIM_OCIDLESTATE_RESET))
+
+#define IS_TIM_OCNIDLE_STATE(__STATE__)    (((__STATE__) == TIM_OCNIDLESTATE_SET) || \
+                                            ((__STATE__) == TIM_OCNIDLESTATE_RESET))
+
+#define IS_TIM_ENCODERINPUT_POLARITY(__POLARITY__)   (((__POLARITY__) == TIM_ENCODERINPUTPOLARITY_RISING)   || \
+                                                      ((__POLARITY__) == TIM_ENCODERINPUTPOLARITY_FALLING))
+
+#define IS_TIM_IC_POLARITY(__POLARITY__)   (((__POLARITY__) == TIM_ICPOLARITY_RISING)   || \
+                                            ((__POLARITY__) == TIM_ICPOLARITY_FALLING)  || \
+                                            ((__POLARITY__) == TIM_ICPOLARITY_BOTHEDGE))
+
+#define IS_TIM_IC_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_ICSELECTION_DIRECTTI) || \
+                                            ((__SELECTION__) == TIM_ICSELECTION_INDIRECTTI) || \
+                                            ((__SELECTION__) == TIM_ICSELECTION_TRC))
+
+#define IS_TIM_IC_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_ICPSC_DIV1) || \
+                                            ((__PRESCALER__) == TIM_ICPSC_DIV2) || \
+                                            ((__PRESCALER__) == TIM_ICPSC_DIV4) || \
+                                            ((__PRESCALER__) == TIM_ICPSC_DIV8))
+
+#define IS_TIM_OPM_MODE(__MODE__)          (((__MODE__) == TIM_OPMODE_SINGLE) || \
+                                            ((__MODE__) == TIM_OPMODE_REPETITIVE))
+
+#define IS_TIM_ENCODER_MODE(__MODE__)      (((__MODE__) == TIM_ENCODERMODE_TI1) || \
+                                            ((__MODE__) == TIM_ENCODERMODE_TI2) || \
+                                            ((__MODE__) == TIM_ENCODERMODE_TI12))
+
+#define IS_TIM_DMA_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFF80FFU) == 0x00000000U) && ((__SOURCE__) != 0x00000000U))
+
+#define IS_TIM_CHANNELS(__CHANNEL__)       (((__CHANNEL__) == TIM_CHANNEL_1) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_2) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_3) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_4) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_5) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_6) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_ALL))
+
+#define IS_TIM_OPM_CHANNELS(__CHANNEL__)   (((__CHANNEL__) == TIM_CHANNEL_1) || \
+                                            ((__CHANNEL__) == TIM_CHANNEL_2))
+
+#define IS_TIM_PERIOD(__HANDLE__, __PERIOD__) \
+  ((IS_TIM_32B_COUNTER_INSTANCE(((__HANDLE__)->Instance)) == 0U) ? (((__PERIOD__) > 0U) && ((__PERIOD__) <= 0x0000FFFFU)) : ((__PERIOD__) > 0U))
+
+#define IS_TIM_COMPLEMENTARY_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \
+                                                    ((__CHANNEL__) == TIM_CHANNEL_2) || \
+                                                    ((__CHANNEL__) == TIM_CHANNEL_3))
+
+#define IS_TIM_CLOCKSOURCE(__CLOCK__) (((__CLOCK__) == TIM_CLOCKSOURCE_INTERNAL) || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE1) || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE2) || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_TI1ED)    || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_TI1)      || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_TI2)      || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR0)     || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR1)     || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR2)     || \
+                                       ((__CLOCK__) == TIM_CLOCKSOURCE_ITR3))
+
+#define IS_TIM_CLOCKPOLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLOCKPOLARITY_INVERTED)    || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_NONINVERTED) || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_RISING)      || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_FALLING)     || \
+                                            ((__POLARITY__) == TIM_CLOCKPOLARITY_BOTHEDGE))
+
+#define IS_TIM_CLOCKPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV1) || \
+                                              ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV2) || \
+                                              ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV4) || \
+                                              ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV8))
+
+#define IS_TIM_CLOCKFILTER(__ICFILTER__)      ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_CLEARINPUT_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLEARINPUTPOLARITY_INVERTED) || \
+                                                  ((__POLARITY__) == TIM_CLEARINPUTPOLARITY_NONINVERTED))
+
+#define IS_TIM_CLEARINPUT_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV1) || \
+                                                    ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV2) || \
+                                                    ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV4) || \
+                                                    ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV8))
+
+#define IS_TIM_CLEARINPUT_FILTER(__ICFILTER__) ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_OSSR_STATE(__STATE__)       (((__STATE__) == TIM_OSSR_ENABLE) || \
+                                            ((__STATE__) == TIM_OSSR_DISABLE))
+
+#define IS_TIM_OSSI_STATE(__STATE__)       (((__STATE__) == TIM_OSSI_ENABLE) || \
+                                            ((__STATE__) == TIM_OSSI_DISABLE))
+
+#define IS_TIM_LOCK_LEVEL(__LEVEL__)       (((__LEVEL__) == TIM_LOCKLEVEL_OFF) || \
+                                            ((__LEVEL__) == TIM_LOCKLEVEL_1)   || \
+                                            ((__LEVEL__) == TIM_LOCKLEVEL_2)   || \
+                                            ((__LEVEL__) == TIM_LOCKLEVEL_3))
+
+#define IS_TIM_BREAK_FILTER(__BRKFILTER__) ((__BRKFILTER__) <= 0xFUL)
+
+
+#define IS_TIM_BREAK_STATE(__STATE__)      (((__STATE__) == TIM_BREAK_ENABLE) || \
+                                            ((__STATE__) == TIM_BREAK_DISABLE))
+
+#define IS_TIM_BREAK_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAKPOLARITY_LOW) || \
+                                             ((__POLARITY__) == TIM_BREAKPOLARITY_HIGH))
+
+#define IS_TIM_BREAK_AFMODE(__AFMODE__) (((__AFMODE__) == TIM_BREAK_AFMODE_INPUT) || \
+                                         ((__AFMODE__) == TIM_BREAK_AFMODE_BIDIRECTIONAL))
+
+
+#define IS_TIM_BREAK2_STATE(__STATE__)     (((__STATE__) == TIM_BREAK2_ENABLE) || \
+                                            ((__STATE__) == TIM_BREAK2_DISABLE))
+
+#define IS_TIM_BREAK2_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAK2POLARITY_LOW) || \
+                                              ((__POLARITY__) == TIM_BREAK2POLARITY_HIGH))
+
+#define IS_TIM_BREAK2_AFMODE(__AFMODE__) (((__AFMODE__) == TIM_BREAK2_AFMODE_INPUT) || \
+                                          ((__AFMODE__) == TIM_BREAK2_AFMODE_BIDIRECTIONAL))
+
+
+#define IS_TIM_AUTOMATIC_OUTPUT_STATE(__STATE__) (((__STATE__) == TIM_AUTOMATICOUTPUT_ENABLE) || \
+                                                  ((__STATE__) == TIM_AUTOMATICOUTPUT_DISABLE))
+
+#define IS_TIM_GROUPCH5(__OCREF__) ((((__OCREF__) & 0x1FFFFFFFU) == 0x00000000U))
+
+#define IS_TIM_TRGO_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO_RESET)  || \
+                                        ((__SOURCE__) == TIM_TRGO_ENABLE) || \
+                                        ((__SOURCE__) == TIM_TRGO_UPDATE) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC1)    || \
+                                        ((__SOURCE__) == TIM_TRGO_OC1REF) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC2REF) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC3REF) || \
+                                        ((__SOURCE__) == TIM_TRGO_OC4REF))
+
+#define IS_TIM_TRGO2_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO2_RESET)                        || \
+                                         ((__SOURCE__) == TIM_TRGO2_ENABLE)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_UPDATE)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC1)                          || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC1REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC2REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC3REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC3REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC4REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC5REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC6REF)                       || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC4REF_RISINGFALLING)         || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC6REF_RISINGFALLING)         || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC4REF_RISING_OC6REF_RISING)  || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC4REF_RISING_OC6REF_FALLING) || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC5REF_RISING_OC6REF_RISING)  || \
+                                         ((__SOURCE__) == TIM_TRGO2_OC5REF_RISING_OC6REF_FALLING))
+
+#define IS_TIM_MSM_STATE(__STATE__)      (((__STATE__) == TIM_MASTERSLAVEMODE_ENABLE) || \
+                                          ((__STATE__) == TIM_MASTERSLAVEMODE_DISABLE))
+
+#define IS_TIM_SLAVE_MODE(__MODE__) (((__MODE__) == TIM_SLAVEMODE_DISABLE)   || \
+                                     ((__MODE__) == TIM_SLAVEMODE_RESET)     || \
+                                     ((__MODE__) == TIM_SLAVEMODE_GATED)     || \
+                                     ((__MODE__) == TIM_SLAVEMODE_TRIGGER)   || \
+                                     ((__MODE__) == TIM_SLAVEMODE_EXTERNAL1) || \
+                                     ((__MODE__) == TIM_SLAVEMODE_COMBINED_RESETTRIGGER))
+
+#define IS_TIM_PWM_MODE(__MODE__) (((__MODE__) == TIM_OCMODE_PWM1)               || \
+                                   ((__MODE__) == TIM_OCMODE_PWM2)               || \
+                                   ((__MODE__) == TIM_OCMODE_COMBINED_PWM1)      || \
+                                   ((__MODE__) == TIM_OCMODE_COMBINED_PWM2)      || \
+                                   ((__MODE__) == TIM_OCMODE_ASSYMETRIC_PWM1)    || \
+                                   ((__MODE__) == TIM_OCMODE_ASSYMETRIC_PWM2))
+
+#define IS_TIM_OC_MODE(__MODE__)  (((__MODE__) == TIM_OCMODE_TIMING)             || \
+                                   ((__MODE__) == TIM_OCMODE_ACTIVE)             || \
+                                   ((__MODE__) == TIM_OCMODE_INACTIVE)           || \
+                                   ((__MODE__) == TIM_OCMODE_TOGGLE)             || \
+                                   ((__MODE__) == TIM_OCMODE_FORCED_ACTIVE)      || \
+                                   ((__MODE__) == TIM_OCMODE_FORCED_INACTIVE)    || \
+                                   ((__MODE__) == TIM_OCMODE_RETRIGERRABLE_OPM1) || \
+                                   ((__MODE__) == TIM_OCMODE_RETRIGERRABLE_OPM2))
+
+#define IS_TIM_TRIGGER_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0)    || \
+                                                 ((__SELECTION__) == TIM_TS_ITR1)    || \
+                                                 ((__SELECTION__) == TIM_TS_ITR2)    || \
+                                                 ((__SELECTION__) == TIM_TS_ITR3)    || \
+                                                 ((__SELECTION__) == TIM_TS_TI1F_ED) || \
+                                                 ((__SELECTION__) == TIM_TS_TI1FP1)  || \
+                                                 ((__SELECTION__) == TIM_TS_TI2FP2)  || \
+                                                 ((__SELECTION__) == TIM_TS_ETRF))
+
+#define IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0) || \
+                                                               ((__SELECTION__) == TIM_TS_ITR1) || \
+                                                               ((__SELECTION__) == TIM_TS_ITR2) || \
+                                                               ((__SELECTION__) == TIM_TS_ITR3) || \
+                                                               ((__SELECTION__) == TIM_TS_NONE))
+
+#define IS_TIM_TRIGGERPOLARITY(__POLARITY__)   (((__POLARITY__) == TIM_TRIGGERPOLARITY_INVERTED   ) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_NONINVERTED) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_RISING     ) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_FALLING    ) || \
+                                                ((__POLARITY__) == TIM_TRIGGERPOLARITY_BOTHEDGE   ))
+
+#define IS_TIM_TRIGGERPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV1) || \
+                                                ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV2) || \
+                                                ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV4) || \
+                                                ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV8))
+
+#define IS_TIM_TRIGGERFILTER(__ICFILTER__) ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_TI1SELECTION(__TI1SELECTION__)  (((__TI1SELECTION__) == TIM_TI1SELECTION_CH1) || \
+                                                ((__TI1SELECTION__) == TIM_TI1SELECTION_XORCOMBINATION))
+
+#define IS_TIM_DMA_LENGTH(__LENGTH__)      (((__LENGTH__) == TIM_DMABURSTLENGTH_1TRANSFER)   || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_2TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_3TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_4TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_5TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_6TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_7TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_8TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_9TRANSFERS)  || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_10TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_11TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_12TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_13TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_14TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_15TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_16TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_17TRANSFERS) || \
+                                            ((__LENGTH__) == TIM_DMABURSTLENGTH_18TRANSFERS))
+
+#define IS_TIM_DMA_DATA_LENGTH(LENGTH) (((LENGTH) >= 0x1U) && ((LENGTH) < 0x10000U))
+
+#define IS_TIM_IC_FILTER(__ICFILTER__)   ((__ICFILTER__) <= 0xFU)
+
+#define IS_TIM_DEADTIME(__DEADTIME__)    ((__DEADTIME__) <= 0xFFU)
+
+#define IS_TIM_BREAK_SYSTEM(__CONFIG__)    (((__CONFIG__) == TIM_BREAK_SYSTEM_ECC)                  || \
+                                            ((__CONFIG__) == TIM_BREAK_SYSTEM_PVD)                  || \
+                                            ((__CONFIG__) == TIM_BREAK_SYSTEM_SRAM2_PARITY_ERROR)   || \
+                                            ((__CONFIG__) == TIM_BREAK_SYSTEM_LOCKUP))
+
+#define IS_TIM_SLAVEMODE_TRIGGER_ENABLED(__TRIGGER__) (((__TRIGGER__) == TIM_SLAVEMODE_TRIGGER) || \
+                                                       ((__TRIGGER__) == TIM_SLAVEMODE_COMBINED_RESETTRIGGER))
+
+#define TIM_SET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__, __ICPSC__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= (__ICPSC__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= ((__ICPSC__) << 8U)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= (__ICPSC__)) :\
+   ((__HANDLE__)->Instance->CCMR2 |= ((__ICPSC__) << 8U)))
+
+#define TIM_RESET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC) :\
+   ((__HANDLE__)->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC))
+
+#define TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER |= (__POLARITY__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 4U)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 8U)) :\
+   ((__HANDLE__)->Instance->CCER |= (((__POLARITY__) << 12U))))
+
+#define TIM_RESET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP)) :\
+   ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP)))
+
+#define TIM_CHANNEL_STATE_GET(__HANDLE__, __CHANNEL__)\
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? (__HANDLE__)->ChannelState[0] :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? (__HANDLE__)->ChannelState[1] :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? (__HANDLE__)->ChannelState[2] :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? (__HANDLE__)->ChannelState[3] :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? (__HANDLE__)->ChannelState[4] :\
+   (__HANDLE__)->ChannelState[5])
+
+#define TIM_CHANNEL_STATE_SET(__HANDLE__, __CHANNEL__, __CHANNEL_STATE__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->ChannelState[0] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->ChannelState[1] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->ChannelState[2] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->ChannelState[3] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->ChannelState[4] = (__CHANNEL_STATE__)) :\
+   ((__HANDLE__)->ChannelState[5] = (__CHANNEL_STATE__)))
+
+#define TIM_CHANNEL_STATE_SET_ALL(__HANDLE__,  __CHANNEL_STATE__) do { \
+                                                                       (__HANDLE__)->ChannelState[0]  = \
+                                                                       (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[1]  = \
+                                                                       (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[2]  = \
+                                                                       (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[3]  = \
+                                                                       (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[4]  = \
+                                                                       (__CHANNEL_STATE__);  \
+                                                                       (__HANDLE__)->ChannelState[5]  = \
+                                                                       (__CHANNEL_STATE__);  \
+                                                                     } while(0)
+
+#define TIM_CHANNEL_N_STATE_GET(__HANDLE__, __CHANNEL__)\
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? (__HANDLE__)->ChannelNState[0] :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? (__HANDLE__)->ChannelNState[1] :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? (__HANDLE__)->ChannelNState[2] :\
+   (__HANDLE__)->ChannelNState[3])
+
+#define TIM_CHANNEL_N_STATE_SET(__HANDLE__, __CHANNEL__, __CHANNEL_STATE__) \
+  (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->ChannelNState[0] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->ChannelNState[1] = (__CHANNEL_STATE__)) :\
+   ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->ChannelNState[2] = (__CHANNEL_STATE__)) :\
+   ((__HANDLE__)->ChannelNState[3] = (__CHANNEL_STATE__)))
+
+#define TIM_CHANNEL_N_STATE_SET_ALL(__HANDLE__,  __CHANNEL_STATE__) do { \
+                                                                         (__HANDLE__)->ChannelNState[0] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                         (__HANDLE__)->ChannelNState[1] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                         (__HANDLE__)->ChannelNState[2] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                         (__HANDLE__)->ChannelNState[3] = \
+                                                                         (__CHANNEL_STATE__);  \
+                                                                       } while(0)
+
+/**
+  * @}
+  */
+/* End of private macros -----------------------------------------------------*/
+
+/* Include TIM HAL Extended module */
+#include "stm32wbxx_hal_tim_ex.h"
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup TIM_Exported_Functions TIM Exported Functions
+  * @{
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group1 TIM Time Base functions
+  *  @brief   Time Base functions
+  * @{
+  */
+/* Time Base functions ********************************************************/
+HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group2 TIM Output Compare functions
+  *  @brief   TIM Output Compare functions
+  * @{
+  */
+/* Timer Output Compare functions *********************************************/
+HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                       uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group3 TIM PWM functions
+  *  @brief   TIM PWM functions
+  * @{
+  */
+/* Timer PWM functions ********************************************************/
+HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                        uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group4 TIM Input Capture functions
+  *  @brief   TIM Input Capture functions
+  * @{
+  */
+/* Timer Input Capture functions **********************************************/
+HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim);
+HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group5 TIM One Pulse functions
+  *  @brief   TIM One Pulse functions
+  * @{
+  */
+/* Timer One Pulse functions **************************************************/
+HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode);
+HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group6 TIM Encoder functions
+  *  @brief   TIM Encoder functions
+  * @{
+  */
+/* Timer Encoder functions ****************************************************/
+HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim,  TIM_Encoder_InitTypeDef *sConfig);
+HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim);
+void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim);
+/* Blocking mode: Polling */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: Interrupt */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
+/* Non-Blocking mode: DMA */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1,
+                                            uint32_t *pData2, uint16_t Length);
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @addtogroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+  *  @brief   IRQ handler management
+  * @{
+  */
+/* Interrupt Handler functions  ***********************************************/
+void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group8 TIM Peripheral Control functions
+  *  @brief   Peripheral Control functions
+  * @{
+  */
+/* Control functions  *********************************************************/
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_OC_InitTypeDef *sConfig,
+                                           uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_OC_InitTypeDef *sConfig,
+                                            uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig,
+                                           uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef *sConfig,
+                                                 uint32_t OutputChannel,  uint32_t InputChannel);
+HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim,
+                                           const TIM_ClearInputConfigTypeDef *sClearInputConfig,
+                                           uint32_t Channel);
+HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig);
+HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection);
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig);
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig);
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                              uint32_t BurstRequestSrc, const uint32_t  *BurstBuffer, uint32_t  BurstLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                   uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+                                                   uint32_t BurstLength,  uint32_t DataLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc);
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                             uint32_t BurstRequestSrc, uint32_t  *BurstBuffer, uint32_t  BurstLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                  uint32_t BurstRequestSrc, uint32_t  *BurstBuffer,
+                                                  uint32_t  BurstLength, uint32_t  DataLength);
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc);
+HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource);
+uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel);
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions
+  *  @brief   TIM Callbacks functions
+  * @{
+  */
+/* Callback in non blocking modes (Interrupt and DMA) *************************/
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_PWM_PulseFinishedHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_TriggerHalfCpltCallback(TIM_HandleTypeDef *htim);
+void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim);
+
+/* Callbacks Register/UnRegister functions  ***********************************/
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+HAL_StatusTypeDef HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID,
+                                           pTIM_CallbackTypeDef pCallback);
+HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group10 TIM Peripheral State functions
+  *  @brief  Peripheral State functions
+  * @{
+  */
+/* Peripheral State functions  ************************************************/
+HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim);
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim);
+
+/* Peripheral Channel state functions  ************************************************/
+HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim);
+HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim,  uint32_t Channel);
+HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim);
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+/* End of exported functions -------------------------------------------------*/
+
+/* Private functions----------------------------------------------------------*/
+/** @defgroup TIM_Private_Functions TIM Private Functions
+  * @{
+  */
+void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure);
+void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter);
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+void TIM_ETR_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler,
+                       uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter);
+
+void TIM_DMADelayPulseHalfCplt(DMA_HandleTypeDef *hdma);
+void TIM_DMAError(DMA_HandleTypeDef *hdma);
+void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma);
+void TIM_DMACaptureHalfCplt(DMA_HandleTypeDef *hdma);
+void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+void TIM_ResetCallback(TIM_HandleTypeDef *htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+/* End of private functions --------------------------------------------------*/
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32WBxx_HAL_TIM_H */

+ 304 - 0
lib/adc/inc/stm32wbxx_nucleo.h

@@ -0,0 +1,304 @@
+/** 
+  ******************************************************************************
+  * @file    stm32wbxx_nucleo.h
+  * @author  MCD Application Team
+  * @brief   This file contains definitions for:
+  *          - LEDs and push-button available on STM32WBXX-Nucleo Kit 
+  *            from STMicroelectronics
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2019-2021 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32WBXX_NUCLEO_H
+#define __STM32WBXX_NUCLEO_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32WBXX_NUCLEO
+  * @{
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+   
+/** @defgroup STM32WBXX_NUCLEO_Exported_Types Exported Types
+  * @{
+  */
+typedef enum 
+{
+  LED1 = 0,
+  LED2 = 1,
+  LED3 = 2,
+  /* Color led aliases */
+  LED_BLUE   = LED1,
+  LED_GREEN  = LED2,
+  LED_RED    = LED3
+}Led_TypeDef;
+
+typedef enum 
+{  
+  BUTTON_SW1 = 0,
+  BUTTON_SW2 = 1,
+  BUTTON_SW3 = 2,
+}Button_TypeDef;
+
+typedef enum 
+{  
+  BUTTON_MODE_GPIO = 0,
+  BUTTON_MODE_EXTI = 1
+}ButtonMode_TypeDef;
+
+typedef enum 
+{ 
+  JOY_NONE  = 0,
+  JOY_SEL   = 1,
+  JOY_DOWN  = 2,
+  JOY_LEFT  = 3,
+  JOY_RIGHT = 4,
+  JOY_UP    = 5
+} JOYState_TypeDef;
+
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32WBXX_NUCLEO_Exported_Constants Exported Constants
+  * @{
+  */ 
+
+/** 
+  * @brief Define for STM32WBXX_NUCLEO board  
+  */ 
+#if !defined (USE_STM32WBXX_NUCLEO)
+ #define USE_STM32WBXX_NUCLEO
+#endif
+
+/** @defgroup STM32WBXX_NUCLEO_LED LED Constants
+  * @{
+  */
+#define LEDn                                    3
+
+#define LED1_PIN                                GPIO_PIN_5
+#define LED1_GPIO_PORT                          GPIOB
+#define LED1_GPIO_CLK_ENABLE()                  __HAL_RCC_GPIOB_CLK_ENABLE()
+#define LED1_GPIO_CLK_DISABLE()                 __HAL_RCC_GPIOB_CLK_DISABLE()
+
+#define LED2_PIN                                GPIO_PIN_0
+#define LED2_GPIO_PORT                          GPIOB
+#define LED2_GPIO_CLK_ENABLE()                  __HAL_RCC_GPIOB_CLK_ENABLE()
+#define LED2_GPIO_CLK_DISABLE()                 __HAL_RCC_GPIOB_CLK_DISABLE()
+
+#define LED3_PIN                                GPIO_PIN_1
+#define LED3_GPIO_PORT                          GPIOB
+#define LED3_GPIO_CLK_ENABLE()                  __HAL_RCC_GPIOB_CLK_ENABLE()
+#define LED3_GPIO_CLK_DISABLE()                 __HAL_RCC_GPIOB_CLK_DISABLE()
+
+#define LEDx_GPIO_CLK_ENABLE(__INDEX__)         __HAL_RCC_GPIOB_CLK_ENABLE() /* All Led on same port */
+#define LEDx_GPIO_CLK_DISABLE(__INDEX__)        __HAL_RCC_GPIOB_CLK_DISABLE() /* All Led on same port */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32WBXX_NUCLEO_BUTTON BUTTON Constants
+  * @{
+  */  
+#define BUTTONn                                 3
+
+/**
+ * @brief Key push-button
+ */
+#define BUTTON_SW1_PIN                          GPIO_PIN_4
+#define BUTTON_SW1_GPIO_PORT                    GPIOC
+#define BUTTON_SW1_GPIO_CLK_ENABLE()            __HAL_RCC_GPIOC_CLK_ENABLE()
+#define BUTTON_SW1_GPIO_CLK_DISABLE()           __HAL_RCC_GPIOC_CLK_DISABLE()
+#define BUTTON_SW1_EXTI_LINE                    GPIO_PIN_4
+#ifdef CORE_CM0PLUS
+#define BUTTON_SW1_EXTI_IRQn                    EXTI15_4_IRQn
+#else
+#define BUTTON_SW1_EXTI_IRQn                    EXTI4_IRQn
+#endif
+
+#define BUTTON_SW2_PIN                          GPIO_PIN_0
+#define BUTTON_SW2_GPIO_PORT                    GPIOD
+#define BUTTON_SW2_GPIO_CLK_ENABLE()            __HAL_RCC_GPIOD_CLK_ENABLE()
+#define BUTTON_SW2_GPIO_CLK_DISABLE()           __HAL_RCC_GPIOD_CLK_DISABLE()
+#define BUTTON_SW2_EXTI_LINE                    GPIO_PIN_0
+#ifdef CORE_CM0PLUS
+#define BUTTON_SW2_EXTI_IRQn                    EXTI1_0_IRQn
+#else
+#define BUTTON_SW2_EXTI_IRQn                    EXTI0_IRQn
+#endif
+
+#define BUTTON_SW3_PIN                          GPIO_PIN_1
+#define BUTTON_SW3_GPIO_PORT                    GPIOD
+#define BUTTON_SW3_GPIO_CLK_ENABLE()            __HAL_RCC_GPIOD_CLK_ENABLE()
+#define BUTTON_SW3_GPIO_CLK_DISABLE()           __HAL_RCC_GPIOD_CLK_DISABLE()
+#define BUTTON_SW3_EXTI_LINE                    GPIO_PIN_1
+#ifdef CORE_CM0PLUS
+#define BUTTON_SW3_EXTI_IRQn                    EXTI1_0_IRQn
+#else
+#define BUTTON_SW3_EXTI_IRQn                    EXTI1_IRQn
+#endif
+
+#define BUTTONx_GPIO_CLK_ENABLE(__INDEX__)    do { if ((__INDEX__) == BUTTON_SW1) BUTTON_SW1_GPIO_CLK_ENABLE(); else \
+                                              if ((__INDEX__) == BUTTON_SW2) BUTTON_SW2_GPIO_CLK_ENABLE(); else \
+                                              if ((__INDEX__) == BUTTON_SW3) BUTTON_SW3_GPIO_CLK_ENABLE();} while(0)
+
+#define BUTTONx_GPIO_CLK_DISABLE(__INDEX__)    do { if ((__INDEX__) == BUTTON_SW1) BUTTON_SW1_GPIO_CLK_DISABLE(); else \
+                                              if ((__INDEX__) == BUTTON_SW2) BUTTON_SW2_GPIO_CLK_DISABLE(); else \
+                                              if ((__INDEX__) == BUTTON_SW3) BUTTON_SW3_GPIO_CLK_DISABLE();} while(0)
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32WBXX_NUCLEO_BUS BUS Constants
+  * @{
+  */
+/*###################### SPI1 ###################################*/
+#define NUCLEO_SPIx                                 SPI1
+#define NUCLEO_SPIx_CLK_ENABLE()                    __HAL_RCC_SPI1_CLK_ENABLE()
+
+#define NUCLEO_SPIx_SCK_AF                          GPIO_AF5_SPI1
+#define NUCLEO_SPIx_SCK_GPIO_PORT                   GPIOA
+#define NUCLEO_SPIx_SCK_PIN                         GPIO_PIN_5
+#define NUCLEO_SPIx_SCK_GPIO_CLK_ENABLE()           __HAL_RCC_GPIOA_CLK_ENABLE()
+#define NUCLEO_SPIx_SCK_GPIO_CLK_DISABLE()          __HAL_RCC_GPIOA_CLK_DISABLE()
+
+#define NUCLEO_SPIx_MISO_MOSI_AF                    GPIO_AF5_SPI1
+#define NUCLEO_SPIx_MISO_MOSI_GPIO_PORT             GPIOA
+#define NUCLEO_SPIx_MISO_MOSI_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
+#define NUCLEO_SPIx_MISO_MOSI_GPIO_CLK_DISABLE()    __HAL_RCC_GPIOA_CLK_DISABLE()
+#define NUCLEO_SPIx_MISO_PIN                        GPIO_PIN_6
+#define NUCLEO_SPIx_MOSI_PIN                        GPIO_PIN_7
+/* Maximum Timeout values for flags waiting loops. These timeouts are not based
+   on accurate values, they just guarantee that the application will not remain
+   stuck if the SPI communication is corrupted.
+   You may modify these timeout values depending on CPU frequency and application
+   conditions (interrupts routines ...). */   
+#define NUCLEO_SPIx_TIMEOUT_MAX                   1000
+
+
+/**
+  * @brief  SD Control Lines management
+  */  
+#define SD_CS_LOW()       HAL_GPIO_WritePin(SD_CS_GPIO_PORT, SD_CS_PIN, GPIO_PIN_RESET)
+#define SD_CS_HIGH()      HAL_GPIO_WritePin(SD_CS_GPIO_PORT, SD_CS_PIN, GPIO_PIN_SET)
+    
+/**
+  * @brief  LCD Control Lines management
+  */
+#define LCD_CS_LOW()      HAL_GPIO_WritePin(LCD_CS_GPIO_PORT, LCD_CS_PIN, GPIO_PIN_RESET)
+#define LCD_CS_HIGH()     HAL_GPIO_WritePin(LCD_CS_GPIO_PORT, LCD_CS_PIN, GPIO_PIN_SET)
+#define LCD_DC_LOW()      HAL_GPIO_WritePin(LCD_DC_GPIO_PORT, LCD_DC_PIN, GPIO_PIN_RESET)
+#define LCD_DC_HIGH()     HAL_GPIO_WritePin(LCD_DC_GPIO_PORT, LCD_DC_PIN, GPIO_PIN_SET)
+
+/**
+  * @brief  SD Control Interface pins
+  */
+#define SD_CS_PIN                                 GPIO_PIN_10
+#define SD_CS_GPIO_PORT                           GPIOC
+#define SD_CS_GPIO_CLK_ENABLE()                   __HAL_RCC_GPIOC_CLK_ENABLE()
+#define SD_CS_GPIO_CLK_DISABLE()                  __HAL_RCC_GPIOC_CLK_DISABLE()
+
+/**
+  * @brief  LCD Control Interface pins
+  */
+#define LCD_CS_PIN                                 GPIO_PIN_4
+#define LCD_CS_GPIO_PORT                           GPIOA
+#define LCD_CS_GPIO_CLK_ENABLE()                   __HAL_RCC_GPIOA_CLK_ENABLE()
+#define LCD_CS_GPIO_CLK_DISABLE()                  __HAL_RCC_GPIOA_CLK_DISABLE()
+
+/**
+  * @brief  LCD Data/Command Interface pins
+  */
+#define LCD_DC_PIN                                 GPIO_PIN_12
+#define LCD_DC_GPIO_PORT                           GPIOC
+#define LCD_DC_GPIO_CLK_ENABLE()                   __HAL_RCC_GPIOC_CLK_ENABLE()
+#define LCD_DC_GPIO_CLK_DISABLE()                  __HAL_RCC_GPIOC_CLK_DISABLE()
+     
+/*##################### ADC1 ###################################*/
+/**
+  * @brief  ADC Interface pins
+  *         used to detect motion of Joystick available on Adafruit 1.8" TFT shield
+  */
+#define NUCLEO_ADCx                                 ADC1
+#define NUCLEO_ADCx_CLK_ENABLE()                    __HAL_RCC_ADC_CLK_ENABLE()
+    
+#define NUCLEO_ADCx_GPIO_PORT                       GPIOA
+#define NUCLEO_ADCx_GPIO_PIN                        GPIO_PIN_0
+#define NUCLEO_ADCx_GPIO_CLK_ENABLE()               __HAL_RCC_GPIOA_CLK_ENABLE()
+#define NUCLEO_ADCx_GPIO_CLK_DISABLE()              __HAL_RCC_GPIOA_CLK_DISABLE()
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32WBXX_NUCLEO_Exported_Functions
+  * @{
+  */
+uint32_t         BSP_GetVersion(void);  
+
+/** @addtogroup STM32WBXX_NUCLEO_LED_Functions
+  * @{
+  */
+void             BSP_LED_Init(Led_TypeDef Led);
+void             BSP_LED_DeInit(Led_TypeDef Led);
+void             BSP_LED_On(Led_TypeDef Led);
+void             BSP_LED_Off(Led_TypeDef Led);
+void             BSP_LED_Toggle(Led_TypeDef Led);
+/**
+  * @}
+  */
+
+/** @addtogroup STM32WBXX_NUCLEO_BUTTON_Functions
+  * @{
+  */
+void             BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode);
+void             BSP_PB_DeInit(Button_TypeDef Button);
+uint32_t         BSP_PB_GetState(Button_TypeDef Button);
+#ifdef HAL_ADC_MODULE_ENABLED
+uint8_t          BSP_JOY_Init(void);
+JOYState_TypeDef BSP_JOY_GetState(void);
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32WBXX_NUCLEO_H */

+ 851 - 0
lib/adc/stm32wbxx_hal.c

@@ -0,0 +1,851 @@
+/**
+  ******************************************************************************
+  * @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   (0x0CU) /*!< [23:16] sub1 version */
+#define __STM32WBxx_HAL_VERSION_SUB2   (0x00U) /*!< [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 period in Hz
+  */
+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 */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 3973 - 0
lib/adc/stm32wbxx_hal_adc.c

@@ -0,0 +1,3973 @@
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_adc.c
+  * @author  MCD Application Team
+  * @brief   This file provides firmware functions to manage the following
+  *          functionalities of the Analog to Digital Converter (ADC)
+  *          peripheral:
+  *           + Initialization and de-initialization functions
+  *             ++ Initialization and Configuration of ADC
+  *           + Operation functions
+  *             ++ Start, stop, get result of conversions of regular
+  *                group, using 3 possible modes: polling, interruption or DMA.
+  *           + Control functions
+  *             ++ Channels configuration on regular group
+  *             ++ Analog Watchdog configuration
+  *           + State functions
+  *             ++ ADC state machine management
+  *             ++ Interrupts and flags management
+  *          Other functions (extended functions) are available in file
+  *          "stm32wbxx_hal_adc_ex.c".
+  ******************************************************************************
+  * @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
+  ==============================================================================
+                     ##### ADC peripheral features #####
+  ==============================================================================
+  [..]
+  (+) 12-bit, 10-bit, 8-bit or 6-bit configurable resolution.
+
+  (+) Interrupt generation at the end of regular conversion and in case of
+      analog watchdog or overrun events.
+
+  (+) Single and continuous conversion modes.
+
+  (+) Scan mode for conversion of several channels sequentially.
+
+  (+) Data alignment with in-built data coherency.
+
+  (+) Programmable sampling time (channel wise)
+
+  (+) External trigger (timer or EXTI) with configurable polarity
+
+  (+) DMA request generation for transfer of conversions data of regular group.
+
+  (+) ADC channels selectable single/differential input.
+
+  (+) ADC offset shared on 4 offset instances.
+  (+) ADC calibration
+
+  (+) ADC conversion of regular group.
+
+  (+) ADC supply requirements: 1.62 V to 3.6 V.
+
+  (+) ADC input range: from Vref- (connected to Vssa) to Vref+ (connected to
+      Vdda or to an external voltage reference).
+
+
+                     ##### How to use this driver #####
+  ==============================================================================
+    [..]
+
+     *** Configuration of top level parameters related to ADC ***
+     ============================================================
+     [..]
+
+    (#) Enable the ADC interface
+        (++) As prerequisite, ADC clock must be configured at RCC top level.
+
+        (++) Two clock settings are mandatory:
+             (+++) ADC clock (core clock, also possibly conversion clock).
+
+             (+++) ADC clock (conversions clock).
+                   Two possible clock sources: synchronous clock derived from AHB2 clock
+                   or asynchronous clock derived from system clock, PLLSAI1 (output divider R) or the PLL system (output divider P)
+                   running up to 64MHz.
+
+             (+++) Example:
+                   Into HAL_ADC_MspInit() (recommended code location) or with
+                   other device clock parameters configuration:
+               (+++) __HAL_RCC_ADC_CLK_ENABLE();                  (mandatory)
+
+               RCC_ADCCLKSOURCE_PLL enable:                       (optional: if asynchronous clock selected)
+               (+++) RCC_PeriphClkInitTypeDef   RCC_PeriphClkInit;
+               (+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
+               (+++) PeriphClkInit.AdcClockSelection    = RCC_ADCCLKSOURCE_PLL;
+               (+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
+
+        (++) ADC clock source and clock prescaler are configured at ADC level with
+             parameter "ClockPrescaler" using function HAL_ADC_Init().
+
+    (#) ADC pins configuration
+         (++) Enable the clock for the ADC GPIOs
+              using macro __HAL_RCC_GPIOx_CLK_ENABLE()
+         (++) Configure these ADC pins in analog mode
+              using function HAL_GPIO_Init()
+
+    (#) Optionally, in case of usage of ADC with interruptions:
+         (++) Configure the NVIC for ADC
+              using function HAL_NVIC_EnableIRQ(ADCx_IRQn)
+         (++) Insert the ADC interruption handler function HAL_ADC_IRQHandler()
+              into the function of corresponding ADC interruption vector
+              ADCx_IRQHandler().
+
+    (#) Optionally, in case of usage of DMA:
+         (++) Configure the DMA (DMA channel, mode normal or circular, ...)
+              using function HAL_DMA_Init().
+         (++) Configure the NVIC for DMA
+              using function HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
+         (++) Insert the ADC interruption handler function HAL_ADC_IRQHandler()
+              into the function of corresponding DMA interruption vector
+              DMAx_Channelx_IRQHandler().
+
+     *** Configuration of ADC, group regular, channels parameters ***
+     ================================================================
+     [..]
+
+    (#) Configure the ADC parameters (resolution, data alignment, ...)
+        and regular group parameters (conversion trigger, sequencer, ...)
+        using function HAL_ADC_Init().
+
+    (#) Configure the channels for regular group parameters (channel number,
+        channel rank into sequencer, ..., into regular group)
+        using function HAL_ADC_ConfigChannel().
+
+    (#) Optionally, configure the analog watchdog parameters (channels
+        monitored, thresholds, ...)
+        using function HAL_ADC_AnalogWDGConfig().
+
+     *** Execution of ADC conversions ***
+     ====================================
+     [..]
+
+    (#) Optionally, perform an automatic ADC calibration to improve the
+        conversion accuracy
+        using function HAL_ADCEx_Calibration_Start().
+
+    (#) ADC driver can be used among three modes: polling, interruption,
+        transfer by DMA.
+
+        (++) ADC conversion by polling:
+          (+++) Activate the ADC peripheral and start conversions
+                using function HAL_ADC_Start()
+          (+++) Wait for ADC conversion completion
+                using function HAL_ADC_PollForConversion()
+          (+++) Retrieve conversion results
+                using function HAL_ADC_GetValue()
+          (+++) Stop conversion and disable the ADC peripheral
+                using function HAL_ADC_Stop()
+
+        (++) ADC conversion by interruption:
+          (+++) Activate the ADC peripheral and start conversions
+                using function HAL_ADC_Start_IT()
+          (+++) Wait for ADC conversion completion by call of function
+                HAL_ADC_ConvCpltCallback()
+                (this function must be implemented in user program)
+          (+++) Retrieve conversion results
+                using function HAL_ADC_GetValue()
+          (+++) Stop conversion and disable the ADC peripheral
+                using function HAL_ADC_Stop_IT()
+
+        (++) ADC conversion with transfer by DMA:
+          (+++) Activate the ADC peripheral and start conversions
+                using function HAL_ADC_Start_DMA()
+          (+++) Wait for ADC conversion completion by call of function
+                HAL_ADC_ConvCpltCallback() or HAL_ADC_ConvHalfCpltCallback()
+                (these functions must be implemented in user program)
+          (+++) Conversion results are automatically transferred by DMA into
+                destination variable address.
+          (+++) Stop conversion and disable the ADC peripheral
+                using function HAL_ADC_Stop_DMA()
+
+     [..]
+
+    (@) Callback functions must be implemented in user program:
+      (+@) HAL_ADC_ErrorCallback()
+      (+@) HAL_ADC_LevelOutOfWindowCallback() (callback of analog watchdog)
+      (+@) HAL_ADC_ConvCpltCallback()
+      (+@) HAL_ADC_ConvHalfCpltCallback
+
+     *** Deinitialization of ADC ***
+     ============================================================
+     [..]
+
+    (#) Disable the ADC interface
+      (++) ADC clock can be hard reset and disabled at RCC top level.
+        (++) Hard reset of ADC peripherals
+             using macro __ADCx_FORCE_RESET(), __ADCx_RELEASE_RESET().
+        (++) ADC clock disable
+             using the equivalent macro/functions as configuration step.
+             (+++) Example:
+                   Into HAL_ADC_MspDeInit() (recommended code location) or with
+                   other device clock parameters configuration:
+               (+++) RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI14;
+               (+++) RCC_OscInitStructure.HSI14State = RCC_HSI14_OFF; (if not used for system clock)
+               (+++) HAL_RCC_OscConfig(&RCC_OscInitStructure);
+
+    (#) ADC pins configuration
+         (++) Disable the clock for the ADC GPIOs
+              using macro __HAL_RCC_GPIOx_CLK_DISABLE()
+
+    (#) Optionally, in case of usage of ADC with interruptions:
+         (++) Disable the NVIC for ADC
+              using function HAL_NVIC_EnableIRQ(ADCx_IRQn)
+
+    (#) Optionally, in case of usage of DMA:
+         (++) Deinitialize the DMA
+              using function HAL_DMA_Init().
+         (++) Disable the NVIC for DMA
+              using function HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
+
+    [..]
+
+    *** Callback registration ***
+    =============================================
+    [..]
+
+     The compilation flag USE_HAL_ADC_REGISTER_CALLBACKS, when set to 1,
+     allows the user to configure dynamically the driver callbacks.
+     Use Functions HAL_ADC_RegisterCallback()
+     to register an interrupt callback.
+    [..]
+
+     Function HAL_ADC_RegisterCallback() allows to register following callbacks:
+       (+) ConvCpltCallback               : ADC conversion complete callback
+       (+) ConvHalfCpltCallback           : ADC conversion DMA half-transfer callback
+       (+) LevelOutOfWindowCallback       : ADC analog watchdog 1 callback
+       (+) ErrorCallback                  : ADC error callback
+       (+) InjectedConvCpltCallback       : ADC group injected conversion complete callback
+       (+) InjectedQueueOverflowCallback  : ADC group injected context queue overflow callback
+       (+) LevelOutOfWindow2Callback      : ADC analog watchdog 2 callback
+       (+) LevelOutOfWindow3Callback      : ADC analog watchdog 3 callback
+       (+) EndOfSamplingCallback          : ADC end of sampling callback
+       (+) MspInitCallback                : ADC Msp Init callback
+       (+) MspDeInitCallback              : ADC 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_ADC_UnRegisterCallback to reset a callback to the default
+     weak function.
+    [..]
+
+     HAL_ADC_UnRegisterCallback takes as parameters the HAL peripheral handle,
+     and the Callback ID.
+     This function allows to reset following callbacks:
+       (+) ConvCpltCallback               : ADC conversion complete callback
+       (+) ConvHalfCpltCallback           : ADC conversion DMA half-transfer callback
+       (+) LevelOutOfWindowCallback       : ADC analog watchdog 1 callback
+       (+) ErrorCallback                  : ADC error callback
+       (+) InjectedConvCpltCallback       : ADC group injected conversion complete callback
+       (+) InjectedQueueOverflowCallback  : ADC group injected context queue overflow callback
+       (+) LevelOutOfWindow2Callback      : ADC analog watchdog 2 callback
+       (+) LevelOutOfWindow3Callback      : ADC analog watchdog 3 callback
+       (+) EndOfSamplingCallback          : ADC end of sampling callback
+       (+) MspInitCallback                : ADC Msp Init callback
+       (+) MspDeInitCallback              : ADC Msp DeInit callback
+     [..]
+
+     By default, after the HAL_ADC_Init() and when the state is HAL_ADC_STATE_RESET
+     all callbacks are set to the corresponding weak functions:
+     examples HAL_ADC_ConvCpltCallback(), HAL_ADC_ErrorCallback().
+     Exception done for MspInit and MspDeInit functions that are
+     reset to the legacy weak functions in the HAL_ADC_Init()/ HAL_ADC_DeInit() only when
+     these callbacks are null (not registered beforehand).
+    [..]
+
+     If MspInit or MspDeInit are not null, the HAL_ADC_Init()/ HAL_ADC_DeInit()
+     keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+     [..]
+
+     Callbacks can be registered/unregistered in HAL_ADC_STATE_READY state only.
+     Exception done MspInit/MspDeInit functions that can be registered/unregistered
+     in HAL_ADC_STATE_READY or HAL_ADC_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_ADC_RegisterCallback() before calling HAL_ADC_DeInit()
+     or HAL_ADC_Init() function.
+     [..]
+
+     When the compilation flag USE_HAL_ADC_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.
+
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup ADC ADC
+  * @brief ADC HAL module driver
+  * @{
+  */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup ADC_Private_Constants ADC Private Constants
+  * @{
+  */
+
+#define ADC_CFGR_FIELDS_1  ((ADC_CFGR_RES    | ADC_CFGR_ALIGN   |\
+                             ADC_CFGR_CONT   | ADC_CFGR_OVRMOD  |\
+                             ADC_CFGR_DISCEN | ADC_CFGR_DISCNUM |\
+                             ADC_CFGR_EXTEN  | ADC_CFGR_EXTSEL))   /*!< ADC_CFGR fields of parameters that can be updated
+                                                                        when no regular conversion is on-going */
+
+/* Timeout values for ADC operations (enable settling time,                   */
+/*   disable settling time, ...).                                             */
+/*   Values defined to be higher than worst cases: low clock frequency,       */
+/*   maximum prescalers.                                                      */
+#define ADC_ENABLE_TIMEOUT              (2UL)    /*!< ADC enable time-out value  */
+#define ADC_DISABLE_TIMEOUT             (2UL)    /*!< ADC disable time-out value */
+
+/* Timeout to wait for current conversion on going to be completed.           */
+/* Timeout fixed to longest ADC conversion possible, for 1 channel:           */
+/*   - maximum sampling time (640.5 adc_clk)                                  */
+/*   - ADC resolution (Tsar 12 bits= 12.5 adc_clk)                            */
+/*   - System clock / ADC clock <= 4096 (hypothesis of maximum clock ratio)   */
+/*   - ADC oversampling ratio 256                                             */
+/*   Calculation: 653 * 4096 * 256 CPU clock cycles max                       */
+/* Unit: cycles of CPU clock.                                                 */
+#define ADC_CONVERSION_TIME_MAX_CPU_CYCLES (653UL * 4096UL * 256UL)  /*!< ADC conversion completion time-out value */
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+/* Register CHSELR bits corresponding to ranks 2 to 8 .                     */
+#define ADC_CHSELR_SQ2_TO_SQ8           (ADC_CHSELR_SQ2 | ADC_CHSELR_SQ3 | ADC_CHSELR_SQ4 | ADC_CHSELR_SQ5 | ADC_CHSELR_SQ6 | ADC_CHSELR_SQ7 | ADC_CHSELR_SQ8)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+
+/**
+  * @}
+  */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup ADC_Exported_Functions ADC Exported Functions
+  * @{
+  */
+
+/** @defgroup ADC_Exported_Functions_Group1 Initialization and de-initialization functions
+  * @brief    ADC Initialization and Configuration functions
+  *
+@verbatim
+ ===============================================================================
+              ##### Initialization and de-initialization functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+      (+) Initialize and configure the ADC.
+      (+) De-initialize the ADC.
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initialize the ADC peripheral and regular group according to
+  *         parameters specified in structure "ADC_InitTypeDef".
+  * @note   As prerequisite, ADC clock must be configured at RCC top level
+  *         (refer to description of RCC configuration for ADC
+  *         in header of this file).
+  * @note   Possibility to update parameters on the fly:
+  *         This function initializes the ADC MSP (HAL_ADC_MspInit()) only when
+  *         coming from ADC state reset. Following calls to this function can
+  *         be used to reconfigure some parameters of ADC_InitTypeDef
+  *         structure on the fly, without modifying MSP configuration. If ADC
+  *         MSP has to be modified again, HAL_ADC_DeInit() must be called
+  *         before HAL_ADC_Init().
+  *         The setting of these parameters is conditioned to ADC state.
+  *         For parameters constraints, see comments of structure
+  *         "ADC_InitTypeDef".
+  * @note   This function configures the ADC within 2 scopes: scope of entire
+  *         ADC and scope of regular group. For parameters details, see comments
+  *         of structure "ADC_InitTypeDef".
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+  uint32_t tmpCFGR = 0UL;
+  uint32_t tmp_adc_reg_is_conversion_on_going;
+  __IO uint32_t wait_loop_index = 0UL;
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  uint32_t tmpCFGR2 = 0UL;
+#else
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Check ADC handle */
+  if (hadc == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_CLOCKPRESCALER(hadc->Init.ClockPrescaler));
+  assert_param(IS_ADC_RESOLUTION(hadc->Init.Resolution));
+  assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign));
+  assert_param(IS_ADC_SCAN_MODE(hadc->Init.ScanConvMode));
+  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+  assert_param(IS_ADC_EXTTRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+  assert_param(IS_ADC_EXTTRIG(hadc, hadc->Init.ExternalTrigConv));
+  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests));
+  assert_param(IS_ADC_EOC_SELECTION(hadc->Init.EOCSelection));
+  assert_param(IS_ADC_OVERRUN(hadc->Init.Overrun));
+  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.LowPowerAutoWait));
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.LowPowerAutoPowerOff));
+  assert_param(IS_ADC_SAMPLE_TIME(hadc->Init.SamplingTimeCommon1));
+  assert_param(IS_ADC_SAMPLE_TIME(hadc->Init.SamplingTimeCommon2));
+  
+  assert_param(IS_ADC_TRIGGER_FREQ(hadc->Init.TriggerFrequencyMode));
+
+  if(hadc->Init.ScanConvMode != ADC_SCAN_DISABLE)
+  {
+    assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode));
+    
+    if(hadc->Init.ScanConvMode == ADC_SCAN_ENABLE)
+    {
+      assert_param(IS_ADC_REGULAR_NB_CONV(hadc->Init.NbrOfConversion));
+    }
+  }
+#else
+  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.OversamplingMode));
+
+  if (hadc->Init.ScanConvMode != ADC_SCAN_DISABLE)
+  {
+    assert_param(IS_ADC_REGULAR_NB_CONV(hadc->Init.NbrOfConversion));
+    assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode));
+
+    if (hadc->Init.DiscontinuousConvMode == ENABLE)
+    {
+      assert_param(IS_ADC_REGULAR_DISCONT_NUMBER(hadc->Init.NbrOfDiscConversion));
+    }
+  }
+
+  /* DISCEN and CONT bits cannot be set at the same time */
+  assert_param(!((hadc->Init.DiscontinuousConvMode == ENABLE) && (hadc->Init.ContinuousConvMode == ENABLE)));
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Actions performed only if ADC is coming from state reset:                */
+  /* - Initialization of ADC MSP                                              */
+  if (hadc->State == HAL_ADC_STATE_RESET)
+  {
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    /* Init the ADC Callback settings */
+    hadc->ConvCpltCallback              = HAL_ADC_ConvCpltCallback;                 /* Legacy weak callback */
+    hadc->ConvHalfCpltCallback          = HAL_ADC_ConvHalfCpltCallback;             /* Legacy weak callback */
+    hadc->LevelOutOfWindowCallback      = HAL_ADC_LevelOutOfWindowCallback;         /* Legacy weak callback */
+    hadc->ErrorCallback                 = HAL_ADC_ErrorCallback;                    /* Legacy weak callback */
+#if !defined(ADC_SUPPORT_2_5_MSPS)
+    hadc->InjectedConvCpltCallback      = HAL_ADCEx_InjectedConvCpltCallback;       /* Legacy weak callback */
+    hadc->InjectedQueueOverflowCallback = HAL_ADCEx_InjectedQueueOverflowCallback;  /* Legacy weak callback */
+#endif  /* !ADC_SUPPORT_2_5_MSPS */
+    hadc->LevelOutOfWindow2Callback     = HAL_ADCEx_LevelOutOfWindow2Callback;      /* Legacy weak callback */
+    hadc->LevelOutOfWindow3Callback     = HAL_ADCEx_LevelOutOfWindow3Callback;      /* Legacy weak callback */
+    hadc->EndOfSamplingCallback         = HAL_ADCEx_EndOfSamplingCallback;          /* Legacy weak callback */
+
+    if (hadc->MspInitCallback == NULL)
+    {
+      hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit  */
+    }
+
+    /* Init the low level hardware */
+    hadc->MspInitCallback(hadc);
+#else
+    /* Init the low level hardware */
+    HAL_ADC_MspInit(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Set ADC error code to none */
+    ADC_CLEAR_ERRORCODE(hadc);
+
+    /* Initialize Lock */
+    hadc->Lock = HAL_UNLOCKED;
+  }
+
+  /* - Exit from deep power-down mode and ADC voltage regulator enable        */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  /* Feature "deep power-down" not available on ADC peripheral of this STM32WB device */
+#else
+  if (LL_ADC_IsDeepPowerDownEnabled(hadc->Instance) != 0UL)
+  {
+    /* Disable ADC deep power down mode */
+    LL_ADC_DisableDeepPowerDown(hadc->Instance);
+
+    /* System was in deep power down mode, calibration must
+     be relaunched or a previously saved calibration factor
+     re-applied once the ADC voltage regulator is enabled */
+  }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  if (LL_ADC_IsInternalRegulatorEnabled(hadc->Instance) == 0UL)
+  {
+    /* Enable ADC internal voltage regulator */
+    LL_ADC_EnableInternalRegulator(hadc->Instance);
+
+    /* Note: Variable divided by 2 to compensate partially              */
+    /*       CPU processing cycles, scaling in us split to not          */
+    /*       exceed 32 bits register capacity and handle low frequency. */
+    wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
+    while (wait_loop_index != 0UL)
+    {
+      wait_loop_index--;
+    }
+  }
+
+  /* Verification that ADC voltage regulator is correctly enabled, whether    */
+  /* or not ADC is coming from state reset (if any potential problem of       */
+  /* clocking, voltage regulator would not be enabled).                       */
+  if (LL_ADC_IsInternalRegulatorEnabled(hadc->Instance) == 0UL)
+  {
+    /* Update ADC state machine to error */
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+    /* Set ADC error code to ADC peripheral internal error */
+    SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  /* Configuration of ADC parameters if previous preliminary actions are      */
+  /* correctly completed and if there is no conversion on going on regular    */
+  /* group (ADC may already be enabled at this point if HAL_ADC_Init() is     */
+  /* called to update a parameter on the fly).                                */
+  tmp_adc_reg_is_conversion_on_going = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+
+  if (((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+      && (tmp_adc_reg_is_conversion_on_going == 0UL)
+     )
+  {
+    /* Set ADC state */
+    ADC_STATE_CLR_SET(hadc->State,
+                      HAL_ADC_STATE_REG_BUSY,
+                      HAL_ADC_STATE_BUSY_INTERNAL);
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    /* Configuration of common ADC parameters                                 */
+    
+    /* Parameters update conditioned to ADC state:                            */
+    /* Parameters that can be updated only when ADC is disabled:              */
+    /*  - Internal voltage regulator (no parameter in HAL ADC init structure) */
+    /*  - Clock configuration                                                 */
+    /*  - ADC resolution                                                      */
+    /* Note: If low power mode AutoPowerOff is enabled, ADC enable            */
+    /*       and disable phases are performed automatically by hardware       */
+    /*       (in this case, flag ADC_FLAG_RDY is not set).                    */
+    if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+    {
+      /* Some parameters of this register are not reset, since they are set   */
+      /* by other functions and must be kept in case of usage of this         */
+      /* function on the fly (update of a parameter of ADC_InitTypeDef        */
+      /* without needing to reconfigure all other ADC groups/channels         */
+      /* parameters):                                                         */
+      /*   - internal measurement paths: Vbat, temperature sensor, Vref       */
+      /*     (set into HAL_ADC_ConfigChannel() )                              */
+      
+      /* Configuration of ADC resolution                                      */
+      MODIFY_REG(hadc->Instance->CFGR1,
+                 ADC_CFGR1_RES        ,
+                 hadc->Init.Resolution );
+      
+      /* Configuration of ADC:                                                */
+      /*  - clock                                                             */
+      /*  - oversampling enable                                               */
+      /*  - oversampling ratio                                                */
+      /*  - oversampling shift                                                */
+      /*  - oversampling discontinuous mode (triggered mode)                  */
+      /*  - trigger frequency mode                                            */
+      tmpCFGR2 |= ( (hadc->Init.ClockPrescaler & ADC_CFGR2_CKMODE) |
+                    hadc->Init.TriggerFrequencyMode
+                    );
+      
+      MODIFY_REG(hadc->Instance->CFGR2,
+                 ADC_CFGR2_CKMODE |
+                 ADC_CFGR2_LFTRIG     ,
+                 tmpCFGR2              );
+      
+      /* Configuration of ADC clock mode: asynchronous clock source           */
+      /* with selectable prescaler.                                           */
+      if (((hadc->Init.ClockPrescaler) != ADC_CLOCK_SYNC_PCLK_DIV1) &&
+          ((hadc->Init.ClockPrescaler) != ADC_CLOCK_SYNC_PCLK_DIV2) &&
+          ((hadc->Init.ClockPrescaler) != ADC_CLOCK_SYNC_PCLK_DIV4))
+      {
+        MODIFY_REG(ADC1_COMMON->CCR                         ,
+                   ADC_CCR_PRESC                            ,
+                   hadc->Init.ClockPrescaler & ADC_CCR_PRESC );
+      }
+    }
+
+    /* Configuration of ADC:                                                  */
+    /*  - discontinuous mode                                                  */
+    /*  - LowPowerAutoWait mode                                               */
+    /*  - LowPowerAutoPowerOff mode                                           */
+    /*  - continuous conversion mode                                          */
+    /*  - overrun                                                             */
+    /*  - external trigger to start conversion                                */
+    /*  - external trigger polarity                                           */
+    /*  - data alignment                                                      */
+    /*  - resolution                                                          */
+    /*  - scan direction                                                      */
+    /*  - DMA continuous request                                              */
+    tmpCFGR |= (ADC_CFGR_AUTOWAIT((uint32_t)hadc->Init.LowPowerAutoWait)        |
+                ADC_CFGR_AUTOOFF((uint32_t)hadc->Init.LowPowerAutoPowerOff)     |
+                ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)    |
+                ADC_CFGR_OVERRUN(hadc->Init.Overrun)                            |
+                hadc->Init.DataAlign                                            |
+                ADC_SCAN_SEQ_MODE(hadc->Init.ScanConvMode)                      |
+                ADC_CFGR_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests)  );
+
+    /* Update setting of discontinuous mode only if continuous mode is disabled */
+    if (hadc->Init.DiscontinuousConvMode == ENABLE)
+    {
+      if (hadc->Init.ContinuousConvMode == DISABLE)
+      {
+        /* Enable the selected ADC group regular discontinuous mode */
+        tmpCFGR |= ADC_CFGR1_DISCEN;
+      }
+      else
+      {
+        /* ADC regular group discontinuous was intended to be enabled,        */
+        /* but ADC regular group modes continuous and sequencer discontinuous */
+        /* cannot be enabled simultaneously.                                  */
+        
+        /* Update ADC state machine to error */
+        SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+        
+        /* Set ADC error code to ADC peripheral internal error */
+        SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+      }
+    }
+
+    /* Enable external trigger if trigger selection is different of software  */
+    /* start.                                                                 */
+    /* Note: This configuration keeps the hardware feature of parameter       */
+    /*       ExternalTrigConvEdge "trigger edge none" equivalent to           */
+    /*       software start.                                                  */
+    if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
+    {
+      tmpCFGR |= ( (hadc->Init.ExternalTrigConv & ADC_CFGR1_EXTSEL) |
+                     hadc->Init.ExternalTrigConvEdge );
+    }
+
+    /* Update ADC configuration register with previous settings */
+    MODIFY_REG(hadc->Instance->CFGR1,
+               ADC_CFGR1_DISCEN    |
+               ADC_CFGR1_AUTOFF    |
+               ADC_CFGR1_CHSELRMOD |
+               ADC_CFGR1_WAIT      |
+               ADC_CFGR1_CONT      |
+               ADC_CFGR1_OVRMOD    |
+               ADC_CFGR1_EXTSEL    |
+               ADC_CFGR1_EXTEN     |
+               ADC_CFGR1_ALIGN     |
+               ADC_CFGR1_SCANDIR   |
+               ADC_CFGR1_DMACFG,
+               tmpCFGR);
+
+    /* Channel sampling time configuration */
+    LL_ADC_SetSamplingTimeCommonChannels(hadc->Instance, LL_ADC_SAMPLINGTIME_COMMON_1, hadc->Init.SamplingTimeCommon1);
+    LL_ADC_SetSamplingTimeCommonChannels(hadc->Instance, LL_ADC_SAMPLINGTIME_COMMON_2, hadc->Init.SamplingTimeCommon2);
+
+    /* Configuration of regular group sequencer:                              */
+    /* - if scan mode is disabled, regular channels sequence length is set to */
+    /*   0x00: 1 channel converted (channel on regular rank 1)                */
+    /*   Parameter "NbrOfConversion" is discarded.                            */
+    /*   Note: Scan mode is not present by hardware on this device, but       */
+    /*   emulated by software for alignment over all STM32 devices.           */
+    /* - if scan mode is enabled, regular channels sequence length is set to  */
+    /*   parameter "NbrOfConversion".                                         */
+    /*   Channels must be configured into each rank using function            */
+    /*   "HAL_ADC_ConfigChannel()".                                           */
+    if(hadc->Init.ScanConvMode == ADC_SCAN_DISABLE)
+    {
+      /* Set sequencer scan length by clearing ranks above rank 1             */
+      /* and do not modify rank 1 value.                                      */
+      SET_BIT(hadc->Instance->CHSELR,
+              ADC_CHSELR_SQ2_TO_SQ8);
+    }
+    else if(hadc->Init.ScanConvMode == ADC_SCAN_ENABLE)
+    {
+      /* Set ADC group regular sequencer:                                   */
+      /*  - Set ADC group regular sequencer to value memorized              */
+      /*    in HAL ADC handle                                               */
+      /*    Note: This value maybe be initialized at a unknown value,       */
+      /*          therefore after the first call of "HAL_ADC_Init()",       */
+      /*          each rank corresponding to parameter "NbrOfConversion"    */
+      /*          must be set using "HAL_ADC_ConfigChannel()".              */
+      /*  - Set sequencer scan length by clearing ranks above maximum rank  */
+      /*    and do not modify other ranks value.                            */
+      MODIFY_REG(hadc->Instance->CHSELR,
+                  ADC_CHSELR_SQ_ALL,
+                  ((ADC_CHSELR_SQ2_TO_SQ8 << (((hadc->Init.NbrOfConversion - 1UL) * ADC_REGULAR_RANK_2) & 0x1FUL)) |
+                   (hadc->ADCGroupRegularSequencerRanks))
+                );
+    }
+
+    /* Check back that ADC registers have effectively been configured to      */
+    /* ensure of no potential problem of ADC core peripheral clocking.        */
+    /* Check through register CFGR1 (excluding analog watchdog configuration: */
+    /* set into separate dedicated function, and bits of ADC resolution set   */
+    /* out of temporary variable 'tmpCFGR').                                  */
+    if ((hadc->Instance->CFGR1 & ~(ADC_CFGR1_AWD1CH | ADC_CFGR1_AWD1EN | ADC_CFGR1_AWD1SGL | ADC_CFGR1_RES))
+         == tmpCFGR)
+    {
+      /* Set ADC error code to none */
+      ADC_CLEAR_ERRORCODE(hadc);
+
+      /* Set the ADC state */
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_BUSY_INTERNAL,
+                        HAL_ADC_STATE_READY);
+    }
+    else
+    {
+      /* Update ADC state machine to error */
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_BUSY_INTERNAL,
+                        HAL_ADC_STATE_ERROR_INTERNAL);
+
+      /* Set ADC error code to ADC peripheral internal error */
+      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+      tmp_hal_status = HAL_ERROR;
+    }
+
+#else
+    /* Configuration of common ADC parameters                                 */
+
+    /* Parameters update conditioned to ADC state:                            */
+    /* Parameters that can be updated only when ADC is disabled:              */
+    /*  - clock configuration                                                 */
+    if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+    {
+      if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+      {
+        /* Reset configuration of ADC common register CCR:                      */
+        /*                                                                      */
+        /*   - ADC clock mode and ACC prescaler (CKMODE and PRESC bits)are set  */
+        /*     according to adc->Init.ClockPrescaler. It selects the clock      */
+        /*    source and sets the clock division factor.                        */
+        /*                                                                      */
+        /* Some parameters of this register are not reset, since they are set   */
+        /* by other functions and must be kept in case of usage of this         */
+        /* function on the fly (update of a parameter of ADC_InitTypeDef        */
+        /* without needing to reconfigure all other ADC groups/channels         */
+        /* parameters):                                                         */
+        /*   - when multimode feature is available, multimode-related           */
+        /*     parameters: MDMA, DMACFG, DELAY, DUAL (set by API                */
+        /*     HAL_ADCEx_MultiModeConfigChannel() )                             */
+        /*   - internal measurement paths: Vbat, temperature sensor, Vref       */
+        /*     (set into HAL_ADC_ConfigChannel() or                             */
+        /*     HAL_ADCEx_InjectedConfigChannel() )                              */
+        LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(hadc->Instance), hadc->Init.ClockPrescaler);
+      }
+    }
+
+    /* Configuration of ADC:                                                  */
+    /*  - resolution                               Init.Resolution            */
+    /*  - data alignment                           Init.DataAlign             */
+    /*  - external trigger to start conversion     Init.ExternalTrigConv      */
+    /*  - external trigger polarity                Init.ExternalTrigConvEdge  */
+    /*  - continuous conversion mode               Init.ContinuousConvMode    */
+    /*  - overrun                                  Init.Overrun               */
+    /*  - discontinuous mode                       Init.DiscontinuousConvMode */
+    /*  - discontinuous mode channel count         Init.NbrOfDiscConversion   */
+    tmpCFGR |= (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)           |
+                hadc->Init.Overrun                                                     |
+                hadc->Init.DataAlign                                                   |
+                hadc->Init.Resolution                                                  |
+                ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
+
+    if (hadc->Init.DiscontinuousConvMode == ENABLE)
+    {
+      tmpCFGR |= ADC_CFGR_DISCONTINUOUS_NUM(hadc->Init.NbrOfDiscConversion);
+    }
+
+    /* Enable external trigger if trigger selection is different of software  */
+    /* start.                                                                 */
+    /* Note: This configuration keeps the hardware feature of parameter       */
+    /*       ExternalTrigConvEdge "trigger edge none" equivalent to           */
+    /*       software start.                                                  */
+    if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
+    {
+      tmpCFGR |= ((hadc->Init.ExternalTrigConv & ADC_CFGR_EXTSEL)
+                  | hadc->Init.ExternalTrigConvEdge
+                 );
+    }
+
+    /* Update Configuration Register CFGR */
+    MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_FIELDS_1, tmpCFGR);
+
+    /* Parameters update conditioned to ADC state:                            */
+    /* Parameters that can be updated when ADC is disabled or enabled without */
+    /* conversion on going on regular and injected groups:                    */
+    /*  - DMA continuous request          Init.DMAContinuousRequests          */
+    /*  - LowPowerAutoWait feature        Init.LowPowerAutoWait               */
+    /*  - Oversampling parameters         Init.Oversampling                   */
+    tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+    tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+    if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+        && (tmp_adc_is_conversion_on_going_injected == 0UL)
+       )
+    {
+      tmpCFGR = (ADC_CFGR_DFSDM(hadc)                                            |
+                 ADC_CFGR_AUTOWAIT((uint32_t)hadc->Init.LowPowerAutoWait)        |
+                 ADC_CFGR_DMACONTREQ((uint32_t)hadc->Init.DMAContinuousRequests));
+
+      MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_FIELDS_2, tmpCFGR);
+
+      if (hadc->Init.OversamplingMode == ENABLE)
+      {
+        assert_param(IS_ADC_OVERSAMPLING_RATIO(hadc->Init.Oversampling.Ratio));
+        assert_param(IS_ADC_RIGHT_BIT_SHIFT(hadc->Init.Oversampling.RightBitShift));
+        assert_param(IS_ADC_TRIGGERED_OVERSAMPLING_MODE(hadc->Init.Oversampling.TriggeredMode));
+        assert_param(IS_ADC_REGOVERSAMPLING_MODE(hadc->Init.Oversampling.OversamplingStopReset));
+
+        /* Configuration of Oversampler:                                      */
+        /*  - Oversampling Ratio                                              */
+        /*  - Right bit shift                                                 */
+        /*  - Triggered mode                                                  */
+        /*  - Oversampling mode (continued/resumed)                           */
+        MODIFY_REG(hadc->Instance->CFGR2,
+                   ADC_CFGR2_OVSR  |
+                   ADC_CFGR2_OVSS  |
+                   ADC_CFGR2_TROVS |
+                   ADC_CFGR2_ROVSM,
+                   ADC_CFGR2_ROVSE                       |
+                   hadc->Init.Oversampling.Ratio         |
+                   hadc->Init.Oversampling.RightBitShift |
+                   hadc->Init.Oversampling.TriggeredMode |
+                   hadc->Init.Oversampling.OversamplingStopReset
+                  );
+      }
+      else
+      {
+        /* Disable ADC oversampling scope on ADC group regular */
+        CLEAR_BIT(hadc->Instance->CFGR2, ADC_CFGR2_ROVSE);
+      }
+
+    }
+
+    /* Configuration of regular group sequencer:                              */
+    /* - if scan mode is disabled, regular channels sequence length is set to */
+    /*   0x00: 1 channel converted (channel on regular rank 1)                */
+    /*   Parameter "NbrOfConversion" is discarded.                            */
+    /*   Note: Scan mode is not present by hardware on this device, but       */
+    /*   emulated by software for alignment over all STM32 devices.           */
+    /* - if scan mode is enabled, regular channels sequence length is set to  */
+    /*   parameter "NbrOfConversion".                                         */
+
+    if (hadc->Init.ScanConvMode == ADC_SCAN_ENABLE)
+    {
+      /* Set number of ranks in regular group sequencer */
+      MODIFY_REG(hadc->Instance->SQR1, ADC_SQR1_L, (hadc->Init.NbrOfConversion - (uint8_t)1));
+    }
+    else
+    {
+      CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_L);
+    }
+
+    /* Initialize the ADC state */
+    /* Clear HAL_ADC_STATE_BUSY_INTERNAL bit, set HAL_ADC_STATE_READY bit */
+    ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL, HAL_ADC_STATE_READY);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+  }
+  else
+  {
+    /* Update ADC state machine to error */
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Deinitialize the ADC peripheral registers to their default reset
+  *         values, with deinitialization of the ADC MSP.
+  * @note   For devices with several ADCs: reset of ADC common registers is done
+  *         only if all ADCs sharing the same common group are disabled.
+  *         (function "HAL_ADC_MspDeInit()" is also called under the same conditions:
+  *         all ADC instances use the same core clock at RCC level, disabling
+  *         the core clock reset all ADC instances).
+  *         If this is not the case, reset of these common parameters reset is
+  *         bypassed without error reporting: it can be the intended behavior in
+  *         case of reset of a single ADC while the other ADCs sharing the same
+  *         common group is still running.
+  * @note   By default, HAL_ADC_DeInit() set ADC in mode deep power-down:
+  *         this saves more power by reducing leakage currents
+  *         and is particularly interesting before entering MCU low-power modes.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check ADC handle */
+  if (hadc == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Set ADC state */
+  SET_BIT(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL);
+
+  /* Stop potential conversion on going */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+#else
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+  /* Disable ADC peripheral if conversions are effectively stopped            */
+  /* Flush register JSQR: reset the queue sequencer when injected             */
+  /* queue sequencer is enabled and ADC disabled.                             */
+  /* The software and hardware triggers of the injected sequence are both     */
+  /* internally disabled just after the completion of the last valid          */
+  /* injected sequence.                                                       */
+  SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JQM);
+#endif
+
+  /* Disable ADC peripheral if conversions are effectively stopped */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Disable the ADC peripheral */
+    tmp_hal_status = ADC_Disable(hadc);
+
+    /* Check if ADC is effectively disabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Change ADC state */
+      hadc->State = HAL_ADC_STATE_READY;
+    }
+  }
+
+  /* Note: HAL ADC deInit is done independently of ADC conversion stop        */
+  /*       and disable return status. In case of status fail, attempt to      */
+  /*       perform deinitialization anyway and it is up user code in          */
+  /*       in HAL_ADC_MspDeInit() to reset the ADC peripheral using           */
+  /*       system RCC hard reset.                                             */
+
+  /* ========== Reset ADC registers ========== */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+  /* Reset register IER */
+  __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_AWD3  | ADC_IT_AWD2 |
+                              ADC_IT_AWD1  | ADC_IT_OVR  |
+                              ADC_IT_EOS   | ADC_IT_EOC  |
+                              ADC_IT_EOSMP | ADC_IT_RDY   ) );
+
+  /* Reset register ISR */
+  __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_AWD3  | ADC_FLAG_AWD2 |
+                              ADC_FLAG_AWD1  | ADC_FLAG_OVR  |
+                              ADC_FLAG_EOS   | ADC_FLAG_EOC  |
+                              ADC_FLAG_EOSMP | ADC_FLAG_RDY   ) );
+
+  /* Reset register CR */
+  /* Bits ADC_CR_ADCAL, ADC_CR_ADSTP, ADC_CR_ADSTART are in access mode     */
+  /* "read-set": no direct reset applicable.                                */
+  
+  /* Reset register CFGR1 */
+  hadc->Instance->CFGR1 &= ~(ADC_CFGR1_AWD1CH  | ADC_CFGR1_AWD1EN | ADC_CFGR1_AWD1SGL | ADC_CFGR1_DISCEN |
+                             ADC_CFGR1_AUTOFF  | ADC_CFGR1_WAIT   | ADC_CFGR1_CONT    | ADC_CFGR1_OVRMOD |
+                             ADC_CFGR1_EXTEN   | ADC_CFGR1_EXTSEL | ADC_CFGR1_ALIGN   | ADC_CFGR1_RES    |
+                             ADC_CFGR1_SCANDIR | ADC_CFGR1_DMACFG | ADC_CFGR1_DMAEN   |
+                             ADC_CFGR1_CHSELRMOD);
+
+  /* Reset register CFGR2 */
+  /* Note: Update of ADC clock mode is conditioned to ADC state disabled:   */
+  /*       already done above.                                              */
+  hadc->Instance->CFGR2 &= ~ADC_CFGR2_CKMODE;
+
+  /* Reset register SMPR */
+  hadc->Instance->SMPR &= ~ADC_SMPR_SMP1;
+
+  /* Reset register TR */
+  hadc->Instance->TR &= ~(ADC_TR_HT | ADC_TR_LT);
+
+  /* Reset register CHSELR */
+  hadc->Instance->CHSELR &= ~(ADC_CHSELR_SQ_ALL);
+
+  /* Reset register DR */
+  /* bits in access mode read only, no direct reset applicable */
+
+#else
+  /* Reset register IER */
+  __HAL_ADC_DISABLE_IT(hadc, (
+#if defined(ADC_SUPPORT_2_5_MSPS)
+                              ADC_IT_AWD3  | ADC_IT_AWD2 | ADC_IT_AWD1 |
+                              ADC_IT_EOCAL | ADC_IT_CCRDY |
+#else
+                              ADC_IT_AWD3  | ADC_IT_AWD2 | ADC_IT_AWD1 |
+                              ADC_IT_JEOS  | ADC_IT_JEOC | ADC_IT_JQOVF |
+#endif /* ADC_SUPPORT_2_5_MSPS */
+                              ADC_IT_EOS   | ADC_IT_EOC  | ADC_IT_OVR   |
+                              ADC_IT_EOSMP | ADC_IT_RDY));
+
+  /* Reset register ISR */
+  __HAL_ADC_CLEAR_FLAG(hadc, (
+#if defined(ADC_SUPPORT_2_5_MSPS)
+                              ADC_FLAG_AWD3  | ADC_FLAG_AWD2 | ADC_FLAG_AWD1 |
+                              ADC_FLAG_EOCAL | ADC_FLAG_CCRDY |
+#else
+                              ADC_FLAG_AWD3  | ADC_FLAG_AWD2 | ADC_FLAG_AWD1 |
+                              ADC_FLAG_JEOS  | ADC_FLAG_JEOC | ADC_FLAG_JQOVF |
+#endif /* ADC_SUPPORT_2_5_MSPS */
+                              ADC_FLAG_EOS   | ADC_FLAG_EOC  | ADC_FLAG_OVR  |
+                              ADC_FLAG_EOSMP | ADC_FLAG_RDY));
+
+  /* Reset register CR */
+  /* Bits ADC_CR_JADSTP, ADC_CR_ADSTP, ADC_CR_JADSTART, ADC_CR_ADSTART,
+     ADC_CR_ADCAL, ADC_CR_ADDIS and ADC_CR_ADEN are in access mode "read-set":
+     no direct reset applicable.
+     Update CR register to reset value where doable by software */
+  CLEAR_BIT(hadc->Instance->CR, ADC_CR_ADVREGEN | ADC_CR_ADCALDIF);
+  SET_BIT(hadc->Instance->CR, ADC_CR_DEEPPWD);
+
+  /* Reset register CFGR */
+  CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_FIELDS);
+  SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+  /* Reset register CFGR2 */
+  CLEAR_BIT(hadc->Instance->CFGR2, ADC_CFGR2_ROVSM  | ADC_CFGR2_TROVS   | ADC_CFGR2_OVSS |
+            ADC_CFGR2_OVSR  | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSE);
+
+  /* Reset register SMPR1 */
+  CLEAR_BIT(hadc->Instance->SMPR1, ADC_SMPR1_FIELDS);
+
+  /* Reset register SMPR2 */
+  CLEAR_BIT(hadc->Instance->SMPR2, ADC_SMPR2_SMP18 | ADC_SMPR2_SMP17 | ADC_SMPR2_SMP16 |
+            ADC_SMPR2_SMP15 | ADC_SMPR2_SMP14 | ADC_SMPR2_SMP13 |
+            ADC_SMPR2_SMP12 | ADC_SMPR2_SMP11 | ADC_SMPR2_SMP10);
+
+  /* Reset register TR1 */
+  CLEAR_BIT(hadc->Instance->TR1, ADC_TR1_HT1 | ADC_TR1_LT1);
+
+  /* Reset register TR2 */
+  CLEAR_BIT(hadc->Instance->TR2, ADC_TR2_HT2 | ADC_TR2_LT2);
+
+  /* Reset register TR3 */
+  CLEAR_BIT(hadc->Instance->TR3, ADC_TR3_HT3 | ADC_TR3_LT3);
+
+  /* Reset register SQR1 */
+  CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_SQ4 | ADC_SQR1_SQ3 | ADC_SQR1_SQ2 |
+            ADC_SQR1_SQ1 | ADC_SQR1_L);
+
+  /* Reset register SQR2 */
+  CLEAR_BIT(hadc->Instance->SQR2, ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7 |
+            ADC_SQR2_SQ6 | ADC_SQR2_SQ5);
+
+  /* Reset register SQR3 */
+  CLEAR_BIT(hadc->Instance->SQR3, ADC_SQR3_SQ14 | ADC_SQR3_SQ13 | ADC_SQR3_SQ12 |
+            ADC_SQR3_SQ11 | ADC_SQR3_SQ10);
+
+  /* Reset register SQR4 */
+  CLEAR_BIT(hadc->Instance->SQR4, ADC_SQR4_SQ16 | ADC_SQR4_SQ15);
+
+  /* Register JSQR was reset when the ADC was disabled */
+
+  /* Reset register DR */
+  /* bits in access mode read only, no direct reset applicable*/
+
+  /* Reset register OFR1 */
+  CLEAR_BIT(hadc->Instance->OFR1, ADC_OFR1_OFFSET1_EN | ADC_OFR1_OFFSET1_CH | ADC_OFR1_OFFSET1);
+  /* Reset register OFR2 */
+  CLEAR_BIT(hadc->Instance->OFR2, ADC_OFR2_OFFSET2_EN | ADC_OFR2_OFFSET2_CH | ADC_OFR2_OFFSET2);
+  /* Reset register OFR3 */
+  CLEAR_BIT(hadc->Instance->OFR3, ADC_OFR3_OFFSET3_EN | ADC_OFR3_OFFSET3_CH | ADC_OFR3_OFFSET3);
+  /* Reset register OFR4 */
+  CLEAR_BIT(hadc->Instance->OFR4, ADC_OFR4_OFFSET4_EN | ADC_OFR4_OFFSET4_CH | ADC_OFR4_OFFSET4);
+
+  /* Reset registers JDR1, JDR2, JDR3, JDR4 */
+  /* bits in access mode read only, no direct reset applicable*/
+
+  /* Reset register AWD2CR */
+  CLEAR_BIT(hadc->Instance->AWD2CR, ADC_AWD2CR_AWD2CH);
+
+  /* Reset register AWD3CR */
+  CLEAR_BIT(hadc->Instance->AWD3CR, ADC_AWD3CR_AWD3CH);
+
+  /* Reset register DIFSEL */
+  CLEAR_BIT(hadc->Instance->DIFSEL, ADC_DIFSEL_DIFSEL);
+
+  /* Reset register CALFACT */
+  CLEAR_BIT(hadc->Instance->CALFACT, ADC_CALFACT_CALFACT_D | ADC_CALFACT_CALFACT_S);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+
+  /* ========== Reset common ADC registers ========== */
+
+  /* Software is allowed to change common parameters only when all the other
+     ADCs are disabled.   */
+  if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+  {
+    /* Reset configuration of ADC common register CCR:
+      - clock mode: CKMODE, PRESCEN
+      - multimode related parameters (when this feature is available): MDMA,
+        DMACFG, DELAY, DUAL (set by HAL_ADCEx_MultiModeConfigChannel() API)
+      - internal measurement paths: Vbat, temperature sensor, Vref (set into
+        HAL_ADC_ConfigChannel() or HAL_ADCEx_InjectedConfigChannel() )
+    */
+    ADC_CLEAR_COMMON_CONTROL_REGISTER(hadc);
+  }
+
+  /* DeInit the low level hardware.
+
+     For example:
+    __HAL_RCC_ADC_FORCE_RESET();
+    __HAL_RCC_ADC_RELEASE_RESET();
+    __HAL_RCC_ADC_CLK_DISABLE();
+
+    Keep in mind that all ADCs use the same clock: disabling
+    the clock will reset all ADCs.
+
+  */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+  if (hadc->MspDeInitCallback == NULL)
+  {
+    hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit  */
+  }
+
+  /* DeInit the low level hardware: RCC clock, NVIC */
+  hadc->MspDeInitCallback(hadc);
+#else
+  /* DeInit the low level hardware: RCC clock, NVIC */
+  HAL_ADC_MspDeInit(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+  /* Set ADC error code to none */
+  ADC_CLEAR_ERRORCODE(hadc);
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+  /* Reset HAL ADC handle variable */
+  hadc->ADCGroupRegularSequencerRanks = 0x00000000UL;
+#else
+  /* Reset injected channel configuration parameters */
+  hadc->InjectionConfig.ContextQueue = 0;
+  hadc->InjectionConfig.ChannelCount = 0;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Set ADC state */
+  hadc->State = HAL_ADC_STATE_RESET;
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Initialize the ADC MSP.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADC_MspInit must be implemented in the user file.
+   */
+}
+
+/**
+  * @brief  DeInitialize the ADC MSP.
+  * @param hadc ADC handle
+  * @note   All ADC instances use the same core clock at RCC level, disabling
+  *         the core clock reset all ADC instances).
+  * @retval None
+  */
+__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADC_MspDeInit must be implemented in the user file.
+   */
+}
+
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  Register a User ADC Callback
+  *         To be used instead of the weak predefined callback
+  * @param  hadc Pointer to a ADC_HandleTypeDef structure that contains
+  *                the configuration information for the specified ADC.
+  * @param  CallbackID ID of the callback to be registered
+  *         This parameter can be one of the following values:
+  *          @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID      ADC conversion complete callback ID
+  *          @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID          ADC conversion DMA half-transfer callback ID
+  *          @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID    ADC analog watchdog 1 callback ID
+  *          @arg @ref HAL_ADC_ERROR_CB_ID                    ADC error callback ID
+  *          @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID  ADC group injected conversion complete callback ID
+  *          @arg @ref HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID        ADC group injected context queue overflow callback ID
+  *          @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID    ADC analog watchdog 2 callback ID
+  *          @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID    ADC analog watchdog 3 callback ID
+  *          @arg @ref HAL_ADC_END_OF_SAMPLING_CB_ID          ADC end of sampling callback ID
+  *          @arg @ref HAL_ADC_MSPINIT_CB_ID                  ADC Msp Init callback ID
+  *          @arg @ref HAL_ADC_MSPDEINIT_CB_ID                ADC Msp DeInit callback ID
+  *          @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
+  *          @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
+  * @param  pCallback pointer to the Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_RegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID, pADC_CallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+
+  if ((hadc->State & HAL_ADC_STATE_READY) != 0UL)
+  {
+    switch (CallbackID)
+    {
+      case HAL_ADC_CONVERSION_COMPLETE_CB_ID :
+        hadc->ConvCpltCallback = pCallback;
+        break;
+
+      case HAL_ADC_CONVERSION_HALF_CB_ID :
+        hadc->ConvHalfCpltCallback = pCallback;
+        break;
+
+      case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID :
+        hadc->LevelOutOfWindowCallback = pCallback;
+        break;
+
+      case HAL_ADC_ERROR_CB_ID :
+        hadc->ErrorCallback = pCallback;
+        break;
+
+      case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID :
+        hadc->InjectedConvCpltCallback = pCallback;
+        break;
+
+      case HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID :
+        hadc->InjectedQueueOverflowCallback = pCallback;
+        break;
+
+      case HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID :
+        hadc->LevelOutOfWindow2Callback = pCallback;
+        break;
+
+      case HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID :
+        hadc->LevelOutOfWindow3Callback = pCallback;
+        break;
+
+      case HAL_ADC_END_OF_SAMPLING_CB_ID :
+        hadc->EndOfSamplingCallback = pCallback;
+        break;
+
+      case HAL_ADC_MSPINIT_CB_ID :
+        hadc->MspInitCallback = pCallback;
+        break;
+
+      case HAL_ADC_MSPDEINIT_CB_ID :
+        hadc->MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Update the error code */
+        hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else if (HAL_ADC_STATE_RESET == hadc->State)
+  {
+    switch (CallbackID)
+    {
+      case HAL_ADC_MSPINIT_CB_ID :
+        hadc->MspInitCallback = pCallback;
+        break;
+
+      case HAL_ADC_MSPDEINIT_CB_ID :
+        hadc->MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Update the error code */
+        hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Update the error code */
+    hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Unregister a ADC Callback
+  *         ADC callback is redirected to the weak predefined callback
+  * @param  hadc Pointer to a ADC_HandleTypeDef structure that contains
+  *                the configuration information for the specified ADC.
+  * @param  CallbackID ID of the callback to be unregistered
+  *         This parameter can be one of the following values:
+  *          @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID      ADC conversion complete callback ID
+  *          @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID          ADC conversion DMA half-transfer callback ID
+  *          @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID    ADC analog watchdog 1 callback ID
+  *          @arg @ref HAL_ADC_ERROR_CB_ID                    ADC error callback ID
+  *          @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID  ADC group injected conversion complete callback ID
+  *          @arg @ref HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID        ADC group injected context queue overflow callback ID
+  *          @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID    ADC analog watchdog 2 callback ID
+  *          @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID    ADC analog watchdog 3 callback ID
+  *          @arg @ref HAL_ADC_END_OF_SAMPLING_CB_ID          ADC end of sampling callback ID
+  *          @arg @ref HAL_ADC_MSPINIT_CB_ID                  ADC Msp Init callback ID
+  *          @arg @ref HAL_ADC_MSPDEINIT_CB_ID                ADC Msp DeInit callback ID
+  *          @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
+  *          @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_UnRegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if ((hadc->State & HAL_ADC_STATE_READY) != 0UL)
+  {
+    switch (CallbackID)
+    {
+      case HAL_ADC_CONVERSION_COMPLETE_CB_ID :
+        hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback;
+        break;
+
+      case HAL_ADC_CONVERSION_HALF_CB_ID :
+        hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback;
+        break;
+
+      case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID :
+        hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback;
+        break;
+
+      case HAL_ADC_ERROR_CB_ID :
+        hadc->ErrorCallback = HAL_ADC_ErrorCallback;
+        break;
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+      case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID :
+        hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback;
+        break;
+
+      case HAL_ADC_INJ_QUEUE_OVEFLOW_CB_ID :
+        hadc->InjectedQueueOverflowCallback = HAL_ADCEx_InjectedQueueOverflowCallback;
+        break;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+      case HAL_ADC_LEVEL_OUT_OF_WINDOW_2_CB_ID :
+        hadc->LevelOutOfWindow2Callback = HAL_ADCEx_LevelOutOfWindow2Callback;
+        break;
+
+      case HAL_ADC_LEVEL_OUT_OF_WINDOW_3_CB_ID :
+        hadc->LevelOutOfWindow3Callback = HAL_ADCEx_LevelOutOfWindow3Callback;
+        break;
+
+      case HAL_ADC_END_OF_SAMPLING_CB_ID :
+        hadc->EndOfSamplingCallback = HAL_ADCEx_EndOfSamplingCallback;
+        break;
+
+      case HAL_ADC_MSPINIT_CB_ID :
+        hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit              */
+        break;
+
+      case HAL_ADC_MSPDEINIT_CB_ID :
+        hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit            */
+        break;
+
+      default :
+        /* Update the error code */
+        hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else if (HAL_ADC_STATE_RESET == hadc->State)
+  {
+    switch (CallbackID)
+    {
+      case HAL_ADC_MSPINIT_CB_ID :
+        hadc->MspInitCallback = HAL_ADC_MspInit;                   /* Legacy weak MspInit              */
+        break;
+
+      case HAL_ADC_MSPDEINIT_CB_ID :
+        hadc->MspDeInitCallback = HAL_ADC_MspDeInit;               /* Legacy weak MspDeInit            */
+        break;
+
+      default :
+        /* Update the error code */
+        hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Update the error code */
+    hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  return status;
+}
+
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/** @defgroup ADC_Exported_Functions_Group2 ADC Input and Output operation functions
+  * @brief    ADC IO operation functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### IO operation functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+      (+) Start conversion of regular group.
+      (+) Stop conversion of regular group.
+      (+) Poll for conversion complete on regular group.
+      (+) Poll for conversion event.
+      (+) Get result of regular channel conversion.
+      (+) Start conversion of regular group and enable interruptions.
+      (+) Stop conversion of regular group and disable interruptions.
+      (+) Handle ADC interrupt request
+      (+) Start conversion of regular group and enable DMA transfer.
+      (+) Stop conversion of regular group and disable ADC DMA transfer.
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enable ADC, start conversion of regular group.
+  * @note   Interruptions enabled in this function: None.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Perform ADC enable and conversion start if no conversion is on going */
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+  {
+    /* Process locked */
+    __HAL_LOCK(hadc);
+
+    /* Enable the ADC peripheral */
+    tmp_hal_status = ADC_Enable(hadc);
+
+    /* Start conversion if ADC is effectively enabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Set ADC state                                                        */
+      /* - Clear state bitfield related to regular group conversion results   */
+      /* - Set state bitfield related to regular operation                    */
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+                        HAL_ADC_STATE_REG_BUSY);
+
+      /* Set ADC error code */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+      /* Reset all ADC error code fields */
+      ADC_CLEAR_ERRORCODE(hadc);
+#else
+      /* Check if a conversion is on going on ADC group injected */
+      if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+      {
+        /* Reset ADC error code fields related to regular conversions only */
+        CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+      }
+      else
+      {
+        /* Reset all ADC error code fields */
+        ADC_CLEAR_ERRORCODE(hadc);
+      }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+      /* Clear ADC group regular conversion flag and overrun flag               */
+      /* (To ensure of no unknown state from potential previous ADC operations) */
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+      /* Process unlocked */
+      /* Unlock before starting ADC conversions: in case of potential         */
+      /* interruption, to let the process to ADC IRQ Handler.                 */
+      __HAL_UNLOCK(hadc);
+
+      /* Enable conversion of regular group.                                  */
+      /* If software start has been selected, conversion starts immediately.  */
+      /* If external trigger has been selected, conversion will start at next */
+      /* trigger event.                                                       */
+      /* Start ADC group regular conversion */
+      LL_ADC_REG_StartConversion(hadc->Instance);
+    }
+    else
+    {
+      /* Process unlocked */
+      __HAL_UNLOCK(hadc);
+    }
+  }
+  else
+  {
+    tmp_hal_status = HAL_BUSY;
+  }
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Stop ADC conversion of regular group (and injected channels in
+  *         case of auto_injection mode), disable ADC peripheral.
+  * @note:  ADC peripheral disable is forcing stop of potential
+  *         conversion on injected group. If injected group is under use, it
+  *         should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  /* 1. Stop potential conversion on going, on ADC group regular */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+#else
+  /* 1. Stop potential conversion on going, on ADC groups regular and injected */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Disable ADC peripheral if conversions are effectively stopped */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* 2. Disable the ADC peripheral */
+    tmp_hal_status = ADC_Disable(hadc);
+
+    /* Check if ADC is effectively disabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Set ADC state */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_REG_BUSY,
+                        HAL_ADC_STATE_READY);
+#else
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+                        HAL_ADC_STATE_READY);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Wait for regular group conversion to be completed.
+  * @note   ADC conversion flags EOS (end of sequence) and EOC (end of
+  *         conversion) are cleared by this function, with an exception:
+  *         if low power feature "LowPowerAutoWait" is enabled, flags are
+  *         not cleared to not interfere with this feature until data register
+  *         is read using function HAL_ADC_GetValue().
+  * @note   This function cannot be used in a particular setup: ADC configured
+  *         in DMA mode and polling for end of each conversion (ADC init
+  *         parameter "EOCSelection" set to ADC_EOC_SINGLE_CONV).
+  *         In this case, DMA resets the flag EOC and polling cannot be
+  *         performed on each conversion. Nevertheless, polling can still
+  *         be performed on the complete sequence (ADC init
+  *         parameter "EOCSelection" set to ADC_EOC_SEQ_CONV).
+  * @param hadc ADC handle
+  * @param Timeout Timeout value in millisecond.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
+{
+  uint32_t tickstart;
+  uint32_t tmp_Flag_End;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* If end of conversion selected to end of sequence conversions */
+  if (hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV)
+  {
+    tmp_Flag_End = ADC_FLAG_EOS;
+  }
+  /* If end of conversion selected to end of unitary conversion */
+  else /* ADC_EOC_SINGLE_CONV */
+  {
+    /* Verification that ADC configuration is compliant with polling for      */
+    /* each conversion:                                                       */
+    /* Particular case is ADC configured in DMA mode and ADC sequencer with   */
+    /* several ranks and polling for end of each conversion.                  */
+    /* For code simplicity sake, this particular case is generalized to       */
+    /* ADC configured in DMA mode and and polling for end of each conversion. */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    if(READ_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN) != 0UL)
+#else
+    if(READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMAEN) != 0UL)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    {
+      /* Update ADC state machine to error */
+      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+      return HAL_ERROR;
+    }
+    else
+    {
+      tmp_Flag_End = (ADC_FLAG_EOC);
+    }
+  }
+
+  /* Get tick count */
+  tickstart = HAL_GetTick();
+
+  /* Wait until End of unitary conversion or sequence conversions flag is raised */
+  while ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
+  {
+    /* Check if timeout is disabled (set to infinite wait) */
+    if (Timeout != HAL_MAX_DELAY)
+    {
+      if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+      {
+        /* New check to avoid false timeout detection in case of preemption */
+        if ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
+        {
+          /* Update ADC state machine to timeout */
+          SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+          /* Process unlocked */
+          __HAL_UNLOCK(hadc);
+
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+
+  /* Update ADC state machine */
+  SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+
+  /* Determine whether any further conversion upcoming on group regular       */
+  /* by external trigger, continuous mode or scan sequence on going.          */
+  if ((LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+      && (hadc->Init.ContinuousConvMode == DISABLE)
+     )
+  {
+    /* Check whether end of sequence is reached */
+    if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS))
+    {
+      /* Set ADC state */
+      CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+      if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+      {
+        SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+      }
+    }
+  }
+
+  /* Clear polled flag */
+  if (tmp_Flag_End == ADC_FLAG_EOS)
+  {
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOS);
+  }
+  else
+  {
+    /* Clear end of conversion EOC flag of regular group if low power feature */
+    /* "LowPowerAutoWait " is disabled, to not interfere with this feature    */
+    /* until data register is read using function HAL_ADC_GetValue().         */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    if (READ_BIT(hadc->Instance->CFGR1, ADC_CFGR1_WAIT) == 0UL)
+#else
+    if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_AUTDLY) == 0UL)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    {
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS));
+    }
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Poll for ADC event.
+  * @param hadc ADC handle
+  * @param EventType the ADC event type.
+  *          This parameter can be one of the following values:
+  *            @arg @ref ADC_EOSMP_EVENT  ADC End of Sampling event
+  *            @arg @ref ADC_AWD1_EVENT   ADC Analog watchdog 1 event (main analog watchdog, present on all STM32 devices)
+  *            @arg @ref ADC_AWD2_EVENT   ADC Analog watchdog 2 event (additional analog watchdog, not present on all STM32 families)
+  *            @arg @ref ADC_AWD3_EVENT   ADC Analog watchdog 3 event (additional analog watchdog, not present on all STM32 families)
+  *            @arg @ref ADC_OVR_EVENT    ADC Overrun event
+  *            @arg @ref ADC_JQOVF_EVENT  ADC Injected context queue overflow event (1)
+  *
+  *         (1) On STM32WB series, parameter not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx.
+  * @param Timeout Timeout value in millisecond.
+  * @note   The relevant flag is cleared if found to be set, except for ADC_FLAG_OVR.
+  *         Indeed, the latter is reset only if hadc->Init.Overrun field is set
+  *         to ADC_OVR_DATA_OVERWRITTEN. Otherwise, data register may be potentially overwritten
+  *         by a new converted data as soon as OVR is cleared.
+  *         To reset OVR flag once the preserved data is retrieved, the user can resort
+  *         to macro __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef *hadc, uint32_t EventType, uint32_t Timeout)
+{
+  uint32_t tickstart;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_EVENT_TYPE(EventType));
+
+  /* Get tick count */
+  tickstart = HAL_GetTick();
+
+  /* Check selected event flag */
+  while (__HAL_ADC_GET_FLAG(hadc, EventType) == 0UL)
+  {
+    /* Check if timeout is disabled (set to infinite wait) */
+    if (Timeout != HAL_MAX_DELAY)
+    {
+      if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+      {
+        /* New check to avoid false timeout detection in case of preemption */
+        if (__HAL_ADC_GET_FLAG(hadc, EventType) == 0UL)
+        {
+          /* Update ADC state machine to timeout */
+          SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+          /* Process unlocked */
+          __HAL_UNLOCK(hadc);
+
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+
+  switch (EventType)
+  {
+    /* End Of Sampling event */
+    case ADC_EOSMP_EVENT:
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOSMP);
+
+      /* Clear the End Of Sampling flag */
+      __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP);
+
+      break;
+
+    /* Analog watchdog (level out of window) event */
+    /* Note: In case of several analog watchdog enabled, if needed to know      */
+    /* which one triggered and on which ADCx, test ADC state of analog watchdog */
+    /* flags HAL_ADC_STATE_AWD1/2/3 using function "HAL_ADC_GetState()".        */
+    /* For example:                                                             */
+    /*  " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD1) != 0UL) "          */
+    /*  " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD2) != 0UL) "          */
+    /*  " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD3) != 0UL) "          */
+
+    /* Check analog watchdog 1 flag */
+    case ADC_AWD_EVENT:
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+      /* Clear ADC analog watchdog flag */
+      __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD1);
+
+      break;
+
+    /* Check analog watchdog 2 flag */
+    case ADC_AWD2_EVENT:
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+      /* Clear ADC analog watchdog flag */
+      __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD2);
+
+      break;
+
+    /* Check analog watchdog 3 flag */
+    case ADC_AWD3_EVENT:
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+      /* Clear ADC analog watchdog flag */
+      __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD3);
+
+      break;
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+    /* Injected context queue overflow event */
+    case ADC_JQOVF_EVENT:
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_INJ_JQOVF);
+
+      /* Set ADC error code to Injected context queue overflow */
+      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+
+      /* Clear ADC Injected context queue overflow flag */
+      __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JQOVF);
+
+      break;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+    /* Overrun event */
+    default: /* Case ADC_OVR_EVENT */
+      /* If overrun is set to overwrite previous data, overrun event is not     */
+      /* considered as an error.                                                */
+      /* (cf ref manual "Managing conversions without using the DMA and without */
+      /* overrun ")                                                             */
+      if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
+      {
+        /* Set ADC state */
+        SET_BIT(hadc->State, HAL_ADC_STATE_REG_OVR);
+
+        /* Set ADC error code to overrun */
+        SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_OVR);
+      }
+      else
+      {
+        /* Clear ADC Overrun flag only if Overrun is set to ADC_OVR_DATA_OVERWRITTEN
+           otherwise, data register is potentially overwritten by new converted data as soon
+           as OVR is cleared. */
+        __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+      }
+      break;
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Enable ADC, start conversion of regular group with interruption.
+  * @note   Interruptions enabled in this function according to initialization
+  *         setting : EOC (end of conversion), EOS (end of sequence),
+  *         OVR overrun.
+  *         Each of these interruptions has its dedicated callback function.
+  * @note   To guarantee a proper reset of all interruptions once all the needed
+  *         conversions are obtained, HAL_ADC_Stop_IT() must be called to ensure
+  *         a correct stop of the IT-based conversions.
+  * @note   By default, HAL_ADC_Start_IT() does not enable the End Of Sampling
+  *         interruption. If required (e.g. in case of oversampling with trigger
+  *         mode), the user must:
+  *          1. first clear the EOSMP flag if set with macro __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP)
+  *          2. then enable the EOSMP interrupt with macro __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOSMP)
+  *          before calling HAL_ADC_Start_IT().
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Perform ADC enable and conversion start if no conversion is on going */
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+  {
+    /* Process locked */
+    __HAL_LOCK(hadc);
+
+    /* Enable the ADC peripheral */
+    tmp_hal_status = ADC_Enable(hadc);
+
+    /* Start conversion if ADC is effectively enabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Set ADC state                                                        */
+      /* - Clear state bitfield related to regular group conversion results   */
+      /* - Set state bitfield related to regular operation                    */
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+                        HAL_ADC_STATE_REG_BUSY);
+
+      /* Set ADC error code */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+      /* Reset all ADC error code fields */
+      ADC_CLEAR_ERRORCODE(hadc);
+#else
+      /* Check if a conversion is on going on ADC group injected */
+      if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) != 0UL)
+      {
+        /* Reset ADC error code fields related to regular conversions only */
+        CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+      }
+      else
+      {
+        /* Reset all ADC error code fields */
+        ADC_CLEAR_ERRORCODE(hadc);
+      }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+      /* Clear ADC group regular conversion flag and overrun flag               */
+      /* (To ensure of no unknown state from potential previous ADC operations) */
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+      /* Process unlocked */
+      /* Unlock before starting ADC conversions: in case of potential         */
+      /* interruption, to let the process to ADC IRQ Handler.                 */
+      __HAL_UNLOCK(hadc);
+
+      /* Disable all interruptions before enabling the desired ones */
+      __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+      /* Enable ADC end of conversion interrupt */
+      switch (hadc->Init.EOCSelection)
+      {
+        case ADC_EOC_SEQ_CONV:
+          __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOS);
+          break;
+        /* case ADC_EOC_SINGLE_CONV */
+        default:
+          __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOC);
+          break;
+      }
+
+      /* Enable ADC overrun interrupt */
+      /* If hadc->Init.Overrun is set to ADC_OVR_DATA_PRESERVED, only then is
+         ADC_IT_OVR enabled; otherwise data overwrite is considered as normal
+         behavior and no CPU time is lost for a non-processed interruption */
+      if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
+      {
+        __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+      }
+
+      /* Enable conversion of regular group.                                  */
+      /* If software start has been selected, conversion starts immediately.  */
+      /* If external trigger has been selected, conversion will start at next */
+      /* trigger event.                                                       */
+      /* Start ADC group regular conversion */
+      LL_ADC_REG_StartConversion(hadc->Instance);
+    }
+    else
+    {
+      /* Process unlocked */
+      __HAL_UNLOCK(hadc);
+    }
+
+  }
+  else
+  {
+    tmp_hal_status = HAL_BUSY;
+  }
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Stop ADC conversion of regular group (and injected group in
+  *         case of auto_injection mode), disable interrution of
+  *         end-of-conversion, disable ADC peripheral.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  /* 1. Stop potential conversion on going, on ADC group regular */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+#else
+  /* 1. Stop potential conversion on going, on ADC groups regular and injected */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Disable ADC peripheral if conversions are effectively stopped */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Disable ADC end of conversion interrupt for regular group */
+    /* Disable ADC overrun interrupt */
+    __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+    /* 2. Disable the ADC peripheral */
+    tmp_hal_status = ADC_Disable(hadc);
+
+    /* Check if ADC is effectively disabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Set ADC state */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_REG_BUSY,
+                        HAL_ADC_STATE_READY);
+#else
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+                        HAL_ADC_STATE_READY);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Enable ADC, start conversion of regular group and transfer result through DMA.
+  * @note   Interruptions enabled in this function:
+  *         overrun (if applicable), DMA half transfer, DMA transfer complete.
+  *         Each of these interruptions has its dedicated callback function.
+  * @param hadc ADC handle
+  * @param pData Destination Buffer address.
+  * @param Length Number of data to be transferred from ADC peripheral to memory
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Perform ADC enable and conversion start if no conversion is on going */
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+  {
+    /* Process locked */
+    __HAL_LOCK(hadc);
+
+      /* Enable the ADC peripheral */
+      tmp_hal_status = ADC_Enable(hadc);
+
+      /* Start conversion if ADC is effectively enabled */
+      if (tmp_hal_status == HAL_OK)
+      {
+        /* Set ADC state                                                        */
+        /* - Clear state bitfield related to regular group conversion results   */
+        /* - Set state bitfield related to regular operation                    */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
+                          HAL_ADC_STATE_REG_BUSY);
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+        /* Reset all ADC error code fields */
+        ADC_CLEAR_ERRORCODE(hadc);
+#else
+        /* Check if a conversion is on going on ADC group injected */
+        if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) != 0UL)
+        {
+          /* Reset ADC error code fields related to regular conversions only */
+          CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
+        }
+        else
+        {
+          /* Reset all ADC error code fields */
+          ADC_CLEAR_ERRORCODE(hadc);
+        }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+        /* Set the DMA transfer complete callback */
+        hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
+
+        /* Set the DMA half transfer complete callback */
+        hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
+
+        /* Set the DMA error callback */
+        hadc->DMA_Handle->XferErrorCallback = ADC_DMAError;
+
+
+        /* Manage ADC and DMA start: ADC overrun interruption, DMA start,     */
+        /* ADC start (in case of SW start):                                   */
+
+        /* Clear regular group conversion flag and overrun flag               */
+        /* (To ensure of no unknown state from potential previous ADC         */
+        /* operations)                                                        */
+        __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS | ADC_FLAG_OVR));
+
+        /* Process unlocked */
+        /* Unlock before starting ADC conversions: in case of potential         */
+        /* interruption, to let the process to ADC IRQ Handler.                 */
+        __HAL_UNLOCK(hadc);
+
+        /* With DMA, overrun event is always considered as an error even if
+           hadc->Init.Overrun is set to ADC_OVR_DATA_OVERWRITTEN. Therefore,
+           ADC_IT_OVR is enabled. */
+        __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+        /* Enable ADC DMA mode */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+        SET_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN);
+#else
+        SET_BIT(hadc->Instance->CFGR, ADC_CFGR_DMAEN);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+        /* Start the DMA channel */
+        tmp_hal_status = HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
+
+        /* Enable conversion of regular group.                                  */
+        /* If software start has been selected, conversion starts immediately.  */
+        /* If external trigger has been selected, conversion will start at next */
+        /* trigger event.                                                       */
+        /* Start ADC group regular conversion */
+        LL_ADC_REG_StartConversion(hadc->Instance);
+      }
+      else
+      {
+        /* Process unlocked */
+        __HAL_UNLOCK(hadc);
+      }
+  }
+  else
+  {
+    tmp_hal_status = HAL_BUSY;
+  }
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Stop ADC conversion of regular group (and injected group in
+  *         case of auto_injection mode), disable ADC DMA transfer, disable
+  *         ADC peripheral.
+  * @note:  ADC peripheral disable is forcing stop of potential
+  *         conversion on ADC group injected. If ADC group injected is under use, it
+  *         should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* 1. Stop potential ADC group regular conversion on going */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+#else
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Disable ADC peripheral if conversions are effectively stopped */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Disable ADC DMA (ADC DMA configuration of continuous requests is kept) */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    CLEAR_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN);
+#else
+    CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_DMAEN);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+    /* Disable the DMA channel (in case of DMA in circular mode or stop       */
+    /* while DMA transfer is on going)                                        */
+    if (hadc->DMA_Handle->State == HAL_DMA_STATE_BUSY)
+    {
+      tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+      /* Check if DMA channel effectively disabled */
+      if (tmp_hal_status != HAL_OK)
+      {
+        /* Update ADC state machine to error */
+        SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+      }
+    }
+
+    /* Disable ADC overrun interrupt */
+    __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+    /* 2. Disable the ADC peripheral */
+    /* Update "tmp_hal_status" only if DMA channel disabling passed,          */
+    /* to keep in memory a potential failing status.                          */
+    if (tmp_hal_status == HAL_OK)
+    {
+      tmp_hal_status = ADC_Disable(hadc);
+    }
+    else
+    {
+      (void)ADC_Disable(hadc);
+    }
+
+    /* Check if ADC is effectively disabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Set ADC state */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_REG_BUSY,
+                        HAL_ADC_STATE_READY);
+#else
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+                        HAL_ADC_STATE_READY);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    }
+
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Get ADC regular group conversion result.
+  * @note   Reading register DR automatically clears ADC flag EOC
+  *         (ADC group regular end of unitary conversion).
+  * @note   This function does not clear ADC flag EOS
+  *         (ADC group regular end of sequence conversion).
+  *         Occurrence of flag EOS rising:
+  *          - If sequencer is composed of 1 rank, flag EOS is equivalent
+  *            to flag EOC.
+  *          - If sequencer is composed of several ranks, during the scan
+  *            sequence flag EOC only is raised, at the end of the scan sequence
+  *            both flags EOC and EOS are raised.
+  *         To clear this flag, either use function:
+  *         in programming model IT: @ref HAL_ADC_IRQHandler(), in programming
+  *         model polling: @ref HAL_ADC_PollForConversion()
+  *         or @ref __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_EOS).
+  * @param hadc ADC handle
+  * @retval ADC group regular conversion data
+  */
+uint32_t HAL_ADC_GetValue(const ADC_HandleTypeDef *hadc)
+{
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Note: EOC flag is not cleared here by software because automatically     */
+  /*       cleared by hardware when reading register DR.                      */
+
+  /* Return ADC converted value */
+  return hadc->Instance->DR;
+}
+
+/**
+  * @brief  Handle ADC interrupt request.
+  * @param hadc ADC handle
+  * @retval None
+  */
+void HAL_ADC_IRQHandler(ADC_HandleTypeDef *hadc)
+{
+  uint32_t overrun_error = 0UL; /* flag set if overrun occurrence has to be considered as an error */
+  uint32_t tmp_isr = hadc->Instance->ISR;
+  uint32_t tmp_ier = hadc->Instance->IER;
+#if !defined(ADC_SUPPORT_2_5_MSPS)
+  uint32_t tmp_adc_inj_is_trigger_source_sw_start;
+  uint32_t tmp_adc_reg_is_trigger_source_sw_start;
+  uint32_t tmp_cfgr;
+#endif  /* !ADC_SUPPORT_2_5_MSPS */
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_EOC_SELECTION(hadc->Init.EOCSelection));
+
+  /* ========== Check End of Sampling flag for ADC group regular ========== */
+  if (((tmp_isr & ADC_FLAG_EOSMP) == ADC_FLAG_EOSMP) && ((tmp_ier & ADC_IT_EOSMP) == ADC_IT_EOSMP))
+  {
+    /* Update state machine on end of sampling status if not in error state */
+    if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+    {
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOSMP);
+    }
+
+    /* End Of Sampling callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->EndOfSamplingCallback(hadc);
+#else
+    HAL_ADCEx_EndOfSamplingCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Clear regular group conversion flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP);
+  }
+
+  /* ====== Check ADC group regular end of unitary conversion sequence conversions ===== */
+  if ((((tmp_isr & ADC_FLAG_EOC) == ADC_FLAG_EOC) && ((tmp_ier & ADC_IT_EOC) == ADC_IT_EOC)) ||
+      (((tmp_isr & ADC_FLAG_EOS) == ADC_FLAG_EOS) && ((tmp_ier & ADC_IT_EOS) == ADC_IT_EOS)))
+  {
+    /* Update state machine on conversion status if not in error state */
+    if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+    {
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+    }
+
+    /* Determine whether any further conversion upcoming on group regular     */
+    /* by external trigger, continuous mode or scan sequence on going         */
+    /* to disable interruption.                                               */
+    if (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+    {
+      /* Carry on if continuous mode is disabled */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+      if (READ_BIT (hadc->Instance->CFGR1, ADC_CFGR1_CONT) != ADC_CFGR1_CONT)
+#else
+      if (READ_BIT (hadc->Instance->CFGR, ADC_CFGR_CONT) != ADC_CFGR_CONT)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+      {
+        /* If End of Sequence is reached, disable interrupts */
+        if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS))
+        {
+          /* Allowed to modify bits ADC_IT_EOC/ADC_IT_EOS only if bit         */
+          /* ADSTART==0 (no conversion on going)                              */
+          if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+          {
+            /* Disable ADC end of sequence conversion interrupt */
+            /* Note: Overrun interrupt was enabled with EOC interrupt in      */
+            /* HAL_Start_IT(), but is not disabled here because can be used   */
+            /* by overrun IRQ process below.                                  */
+            __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC | ADC_IT_EOS);
+
+            /* Set ADC state */
+            CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+            if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+            {
+              SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+            }
+          }
+          else
+          {
+            /* Change ADC state to error state */
+            SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+            /* Set ADC error code to ADC peripheral internal error */
+            SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+          }
+        }
+      }
+    }
+
+    /* Conversion complete callback */
+    /* Note: Into callback function "HAL_ADC_ConvCpltCallback()",             */
+    /*       to determine if conversion has been triggered from EOC or EOS,   */
+    /*       possibility to use:                                              */
+    /*        " if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOS)) "                */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->ConvCpltCallback(hadc);
+#else
+    HAL_ADC_ConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Clear regular group conversion flag */
+    /* Note: in case of overrun set to ADC_OVR_DATA_PRESERVED, end of         */
+    /*       conversion flags clear induces the release of the preserved data.*/
+    /*       Therefore, if the preserved data value is needed, it must be     */
+    /*       read preliminarily into HAL_ADC_ConvCpltCallback().              */
+    __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS));
+  }
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+  /* ====== Check ADC group injected end of unitary conversion sequence conversions ===== */
+  if ((((tmp_isr & ADC_FLAG_JEOC) == ADC_FLAG_JEOC) && ((tmp_ier & ADC_IT_JEOC) == ADC_IT_JEOC)) ||
+      (((tmp_isr & ADC_FLAG_JEOS) == ADC_FLAG_JEOS) && ((tmp_ier & ADC_IT_JEOS) == ADC_IT_JEOS)))
+  {
+    /* Update state machine on conversion status if not in error state */
+    if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) == 0UL)
+    {
+      /* Set ADC state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+    }
+
+    /* Retrieve ADC configuration */
+    tmp_adc_inj_is_trigger_source_sw_start = LL_ADC_INJ_IsTriggerSourceSWStart(hadc->Instance);
+    tmp_adc_reg_is_trigger_source_sw_start = LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance);
+    tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+
+    /* Disable interruption if no further conversion upcoming by injected     */
+    /* external trigger or by automatic injected conversion with regular      */
+    /* group having no further conversion upcoming (same conditions as        */
+    /* regular group interruption disabling above),                           */
+    /* and if injected scan sequence is completed.                            */
+    if (tmp_adc_inj_is_trigger_source_sw_start != 0UL)
+    {
+      if ((READ_BIT(tmp_cfgr, ADC_CFGR_JAUTO) == 0UL) ||
+          ((tmp_adc_reg_is_trigger_source_sw_start != 0UL) &&
+           (READ_BIT(tmp_cfgr, ADC_CFGR_CONT) == 0UL)))
+      {
+        /* If End of Sequence is reached, disable interrupts */
+        if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS))
+        {
+          /* Particular case if injected contexts queue is enabled:             */
+          /* when the last context has been fully processed, JSQR is reset      */
+          /* by the hardware. Even if no injected conversion is planned to come */
+          /* (queue empty, triggers are ignored), it can start again            */
+          /* immediately after setting a new context (JADSTART is still set).   */
+          /* Therefore, state of HAL ADC injected group is kept to busy.        */
+          if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQM) == 0UL)
+          {
+            /* Allowed to modify bits ADC_IT_JEOC/ADC_IT_JEOS only if bit       */
+            /* JADSTART==0 (no conversion on going)                             */
+            if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+            {
+              /* Disable ADC end of sequence conversion interrupt  */
+              __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC | ADC_IT_JEOS);
+
+              /* Set ADC state */
+              CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+
+              if ((hadc->State & HAL_ADC_STATE_REG_BUSY) == 0UL)
+              {
+                SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+              }
+            }
+            else
+            {
+              /* Update ADC state machine to error */
+              SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+              /* Set ADC error code to ADC peripheral internal error */
+              SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+            }
+          }
+        }
+      }
+    }
+
+    /* Injected Conversion complete callback */
+    /* Note:  HAL_ADCEx_InjectedConvCpltCallback can resort to
+              if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_JEOS)) or
+              if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_JEOC)) to determine whether
+              interruption has been triggered by end of conversion or end of
+              sequence.    */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->InjectedConvCpltCallback(hadc);
+#else
+    HAL_ADCEx_InjectedConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Clear injected group conversion flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC | ADC_FLAG_JEOS);
+  }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* ========== Check Analog watchdog 1 flag ========== */
+  if (((tmp_isr & ADC_FLAG_AWD1) == ADC_FLAG_AWD1) && ((tmp_ier & ADC_IT_AWD1) == ADC_IT_AWD1))
+  {
+    /* Set ADC state */
+    SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+    /* Level out of window 1 callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->LevelOutOfWindowCallback(hadc);
+#else
+    HAL_ADC_LevelOutOfWindowCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Clear ADC analog watchdog flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD1);
+  }
+
+  /* ========== Check analog watchdog 2 flag ========== */
+  if (((tmp_isr & ADC_FLAG_AWD2) == ADC_FLAG_AWD2) && ((tmp_ier & ADC_IT_AWD2) == ADC_IT_AWD2))
+  {
+    /* Set ADC state */
+    SET_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+    /* Level out of window 2 callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->LevelOutOfWindow2Callback(hadc);
+#else
+    HAL_ADCEx_LevelOutOfWindow2Callback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Clear ADC analog watchdog flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD2);
+  }
+
+  /* ========== Check analog watchdog 3 flag ========== */
+  if (((tmp_isr & ADC_FLAG_AWD3) == ADC_FLAG_AWD3) && ((tmp_ier & ADC_IT_AWD3) == ADC_IT_AWD3))
+  {
+    /* Set ADC state */
+    SET_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+    /* Level out of window 3 callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->LevelOutOfWindow3Callback(hadc);
+#else
+    HAL_ADCEx_LevelOutOfWindow3Callback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+
+    /* Clear ADC analog watchdog flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD3);
+  }
+
+  /* ========== Check Overrun flag ========== */
+  if (((tmp_isr & ADC_FLAG_OVR) == ADC_FLAG_OVR) && ((tmp_ier & ADC_IT_OVR) == ADC_IT_OVR))
+  {
+    /* If overrun is set to overwrite previous data (default setting),        */
+    /* overrun event is not considered as an error.                           */
+    /* (cf ref manual "Managing conversions without using the DMA and without */
+    /* overrun ")                                                             */
+    /* Exception for usage with DMA overrun event always considered as an     */
+    /* error.                                                                 */
+    if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
+    {
+      overrun_error = 1UL;
+    }
+    else
+    {
+      /* Check DMA configuration */
+      if (LL_ADC_REG_GetDMATransfer(hadc->Instance) != LL_ADC_REG_DMA_TRANSFER_NONE)
+      {
+        overrun_error = 1UL;
+      }
+    }
+
+    if (overrun_error == 1UL)
+    {
+      /* Change ADC state to error state */
+      SET_BIT(hadc->State, HAL_ADC_STATE_REG_OVR);
+
+      /* Set ADC error code to overrun */
+      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_OVR);
+
+      /* Error callback */
+      /* Note: In case of overrun, ADC conversion data is preserved until     */
+      /*       flag OVR is reset.                                             */
+      /*       Therefore, old ADC conversion data can be retrieved in         */
+      /*       function "HAL_ADC_ErrorCallback()".                            */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+      hadc->ErrorCallback(hadc);
+#else
+      HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+    }
+
+    /* Clear ADC overrun flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+  }
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+  /* ========== Check Injected context queue overflow flag ========== */
+  if (((tmp_isr & ADC_FLAG_JQOVF) == ADC_FLAG_JQOVF) && ((tmp_ier & ADC_IT_JQOVF) == ADC_IT_JQOVF))
+  {
+    /* Change ADC state to overrun state */
+    SET_BIT(hadc->State, HAL_ADC_STATE_INJ_JQOVF);
+
+    /* Set ADC error code to Injected context queue overflow */
+    SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+
+    /* Clear the Injected context queue overflow flag */
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JQOVF);
+
+    /* Injected context queue overflow callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->InjectedQueueOverflowCallback(hadc);
+#else
+    HAL_ADCEx_InjectedQueueOverflowCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+  }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+}
+
+/**
+  * @brief  Conversion complete callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADC_ConvCpltCallback must be implemented in the user file.
+   */
+}
+
+/**
+  * @brief  Conversion DMA half-transfer callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADC_ConvHalfCpltCallback must be implemented in the user file.
+  */
+}
+
+/**
+  * @brief  Analog watchdog 1 callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADC_LevelOutOfWindowCallback must be implemented in the user file.
+  */
+}
+
+/**
+  * @brief  ADC error callback in non-blocking mode
+  *         (ADC conversion with interruption or transfer by DMA).
+  * @note   In case of error due to overrun when using ADC with DMA transfer
+  *         (HAL ADC handle parameter "ErrorCode" to state "HAL_ADC_ERROR_OVR"):
+  *         - Reinitialize the DMA using function "HAL_ADC_Stop_DMA()".
+  *         - If needed, restart a new ADC conversion using function
+  *           "HAL_ADC_Start_DMA()"
+  *           (this function is also clearing overrun flag)
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADC_ErrorCallback must be implemented in the user file.
+  */
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup ADC_Exported_Functions_Group3 Peripheral Control functions
+  * @brief    Peripheral Control functions
+  *
+@verbatim
+ ===============================================================================
+             ##### Peripheral Control functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+      (+) Configure channels on regular group
+      (+) Configure the analog watchdog
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Configure a channel to be assigned to ADC group regular.
+  * @note   In case of usage of internal measurement channels:
+  *         Vbat/VrefInt/TempSensor.
+  *         These internal paths can be disabled using function
+  *         HAL_ADC_DeInit().
+  * @note   Possibility to update parameters on the fly:
+  *         This function initializes channel into ADC group regular,
+  *         following calls to this function can be used to reconfigure
+  *         some parameters of structure "ADC_ChannelConfTypeDef" on the fly,
+  *         without resetting the ADC.
+  *         The setting of these parameters is conditioned to ADC state:
+  *         Refer to comments of structure "ADC_ChannelConfTypeDef".
+  * @param hadc ADC handle
+  * @param sConfig Structure of ADC channel assigned to ADC group regular.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, const ADC_ChannelConfTypeDef *sConfig)
+{
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+  uint32_t tmp_config_internal_channel;
+  __IO uint32_t wait_loop_index = 0UL;
+  
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_CHANNEL(hadc, sConfig->Channel));
+  assert_param(IS_ADC_SAMPLING_TIME_COMMON(sConfig->SamplingTime));
+  
+  if((hadc->Init.ScanConvMode == ADC_SCAN_SEQ_FIXED)          ||
+     (hadc->Init.ScanConvMode == ADC_SCAN_SEQ_FIXED_BACKWARD)   )
+  {
+    assert_param(IS_ADC_REGULAR_RANK_SEQ_FIXED(sConfig->Rank));
+  }
+  else
+  {
+    assert_param(IS_ADC_REGULAR_NB_CONV(hadc->Init.NbrOfConversion));
+    
+    assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
+  }
+  
+  /* Process locked */
+  __HAL_LOCK(hadc);
+  
+  /* Parameters update conditioned to ADC state:                              */
+  /* Parameters that can be updated when ADC is disabled or enabled without   */
+  /* conversion on going on regular group:                                    */
+  /*  - Channel number                                                        */
+  /*  - Channel sampling time                                                 */
+  /*  - Management of internal measurement channels: VrefInt/TempSensor/Vbat  */
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+  {
+    /* Configure channel: depending on rank setting, add it or remove it from */
+    /* ADC sequencer.                                                         */
+    /* If sequencer set to not fully configurable with channel rank set to    */
+    /* none, remove the channel from the sequencer.                           */
+    /* Otherwise (sequencer set to fully configurable or to to not fully      */
+    /* configurable with channel rank to be set), configure the selected      */
+    /* channel.                                                               */
+    if(sConfig->Rank != ADC_RANK_NONE)
+    {
+      /* Regular sequence configuration */
+      /* Note: ADC channel configuration requires few ADC clock cycles        */
+      /*       to be ready. Processing of ADC settings in this function       */
+      /*       induce that a specific wait time is not necessary.             */
+      /*       For more details on ADC channel configuration ready,           */
+      /*       refer to function "LL_ADC_IsActiveFlag_CCRDY()".               */
+      if((hadc->Init.ScanConvMode == ADC_SCAN_SEQ_FIXED)         ||
+         (hadc->Init.ScanConvMode == ADC_SCAN_SEQ_FIXED_BACKWARD)  )
+      {
+        /* Sequencer set to not fully configurable:                           */
+        /* Set the channel by enabling the corresponding bitfield.            */
+        LL_ADC_REG_SetSequencerChAdd(hadc->Instance, sConfig->Channel);
+      }
+      else
+      {
+        /* Sequencer set to fully configurable:                               */
+        /* Set the channel by entering it into the selected rank.             */
+        
+        /* Memorize the channel set into variable in HAL ADC handle */
+        MODIFY_REG(hadc->ADCGroupRegularSequencerRanks,
+                   ADC_CHSELR_SQ1 << (sConfig->Rank & 0x1FUL),
+                   __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfig->Channel) << (sConfig->Rank & 0x1FUL));
+        
+        /* If the selected rank is below ADC group regular sequencer length,  */
+        /* apply the configuration in ADC register.                           */
+        /* Note: Otherwise, configuration is not applied.                     */
+        /*       To apply it, parameter'NbrOfConversion' must be increased.   */        
+        if(((sConfig->Rank >> 2UL) + 1UL) <= hadc->Init.NbrOfConversion)
+        {
+          LL_ADC_REG_SetSequencerRanks(hadc->Instance, sConfig->Rank, sConfig->Channel);
+        }
+      }
+      
+      /* Set sampling time of the selected ADC channel */
+      LL_ADC_SetChannelSamplingTime(hadc->Instance, sConfig->Channel, sConfig->SamplingTime);
+      
+      /* Management of internal measurement channels: VrefInt/TempSensor/Vbat */
+      /* internal measurement paths enable: If internal channel selected,     */
+      /* enable dedicated internal buffers and path.                          */
+      /* Note: these internal measurement paths can be disabled using         */
+      /*       HAL_ADC_DeInit() or removing the channel from sequencer with   */
+      /*       channel configuration parameter "Rank".                        */
+      if(__LL_ADC_IS_CHANNEL_INTERNAL(sConfig->Channel))
+      {
+        tmp_config_internal_channel = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+        
+        /* If the requested internal measurement path has already been enabled,   */
+        /* bypass the configuration processing.                                   */
+        if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_TEMPSENSOR) == 0UL))
+        {
+          LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_TEMPSENSOR | tmp_config_internal_channel);
+          
+          /* Delay for temperature sensor stabilization time */
+          /* Wait loop initialization and execution */
+          /* Note: Variable divided by 2 to compensate partially              */
+          /*       CPU processing cycles, scaling in us split to not          */
+          /*       exceed 32 bits register capacity and handle low frequency. */
+          wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
+          while(wait_loop_index != 0UL)
+          {
+            wait_loop_index--;
+          }
+        }
+        else if ((sConfig->Channel == ADC_CHANNEL_VBAT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VBAT) == 0UL))
+        {
+          LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VBAT | tmp_config_internal_channel);
+        }
+        else if ((sConfig->Channel == ADC_CHANNEL_VREFINT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VREFINT) == 0UL))
+        {
+          LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VREFINT | tmp_config_internal_channel);
+        }
+        else
+        {
+          /* nothing to do */
+        }
+      }
+    }
+    else
+    {
+      /* Regular sequencer configuration */
+      /* Note: Case of sequencer set to fully configurable:                   */
+      /*       Sequencer rank cannot be disabled, only affected to            */
+      /*       another channel.                                               */
+      /*       To remove a rank, use parameter 'NbrOfConversion".             */
+      if((hadc->Init.ScanConvMode == ADC_SCAN_SEQ_FIXED)         ||
+         (hadc->Init.ScanConvMode == ADC_SCAN_SEQ_FIXED_BACKWARD)  )
+      {
+        /* Sequencer set to not fully configurable:                           */
+        /* Reset the channel by disabling the corresponding bitfield.         */
+        LL_ADC_REG_SetSequencerChRem(hadc->Instance, sConfig->Channel);
+      }
+      
+      /* Management of internal measurement channels: Vbat/VrefInt/TempSensor.  */
+      /* If internal channel selected, enable dedicated internal buffers and    */
+      /* paths.                                                                 */
+      if(__LL_ADC_IS_CHANNEL_INTERNAL(sConfig->Channel))
+      {
+        tmp_config_internal_channel = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+        
+        if (sConfig->Channel == ADC_CHANNEL_TEMPSENSOR)
+        {
+          LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), ~LL_ADC_PATH_INTERNAL_TEMPSENSOR & tmp_config_internal_channel);
+        }
+        else if (sConfig->Channel == ADC_CHANNEL_VBAT)
+        {
+          LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), ~LL_ADC_PATH_INTERNAL_VBAT & tmp_config_internal_channel);
+        }
+        else if (sConfig->Channel == ADC_CHANNEL_VREFINT)
+        {
+          LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), ~LL_ADC_PATH_INTERNAL_VREFINT & tmp_config_internal_channel);
+        }
+        else
+        {
+          /* nothing to do */
+        }
+      }
+    }
+  }
+  
+  /* If a conversion is on going on regular group, no update on regular       */
+  /* channel could be done on neither of the channel configuration structure  */
+  /* parameters.                                                              */
+  else
+  {
+    /* Update ADC state machine to error */
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+    
+    tmp_hal_status = HAL_ERROR;
+  }
+  
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+  
+#else
+  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+  uint32_t tmpOffsetShifted;
+  uint32_t tmp_config_internal_channel;
+  __IO uint32_t wait_loop_index = 0;
+#if !defined(ADC_SUPPORT_2_5_MSPS)
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+#endif /* !ADC_SUPPORT_2_5_MSPS */
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
+  assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
+  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(sConfig->SingleDiff));
+  assert_param(IS_ADC_OFFSET_NUMBER(sConfig->OffsetNumber));
+  assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfig->Offset));
+
+  /* if ROVSE is set, the value of the OFFSETy_EN bit in ADCx_OFRy register is
+     ignored (considered as reset) */
+  assert_param(!((sConfig->OffsetNumber != ADC_OFFSET_NONE) && (hadc->Init.OversamplingMode == ENABLE)));
+
+  /* Verification of channel number */
+  if (sConfig->SingleDiff != ADC_DIFFERENTIAL_ENDED)
+  {
+    assert_param(IS_ADC_CHANNEL(hadc, sConfig->Channel));
+  }
+  else
+  {
+    assert_param(IS_ADC_DIFF_CHANNEL(hadc, sConfig->Channel));
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* Parameters update conditioned to ADC state:                              */
+  /* Parameters that can be updated when ADC is disabled or enabled without   */
+  /* conversion on going on regular group:                                    */
+  /*  - Channel number                                                        */
+  /*  - Channel rank                                                          */
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+  {
+    /* Set ADC group regular sequence: channel on the selected scan sequence rank */
+    LL_ADC_REG_SetSequencerRanks(hadc->Instance, sConfig->Rank, sConfig->Channel);
+
+    /* Parameters update conditioned to ADC state:                              */
+    /* Parameters that can be updated when ADC is disabled or enabled without   */
+    /* conversion on going on regular group:                                    */
+    /*  - Channel sampling time                                                 */
+    /*  - Channel offset                                                        */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+#else
+    tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+    tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+    if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+        && (tmp_adc_is_conversion_on_going_injected == 0UL)
+       )
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    {
+      /* Set sampling time of the selected ADC channel */
+      LL_ADC_SetChannelSamplingTime(hadc->Instance, sConfig->Channel, sConfig->SamplingTime);
+
+      /* Configure the offset: offset enable/disable, channel, offset value */
+
+      /* Shift the offset with respect to the selected ADC resolution. */
+      /* Offset has to be left-aligned on bit 11, the LSB (right bits) are set to 0 */
+      tmpOffsetShifted = ADC_OFFSET_SHIFT_RESOLUTION(hadc, (uint32_t)sConfig->Offset);
+
+      if (sConfig->OffsetNumber != ADC_OFFSET_NONE)
+      {
+        /* Set ADC selected offset number */
+        LL_ADC_SetOffset(hadc->Instance, sConfig->OffsetNumber, sConfig->Channel, tmpOffsetShifted);
+
+      }
+      else
+      {
+        /* Scan each offset register to check if the selected channel is targeted. */
+        /* If this is the case, the corresponding offset number is disabled.       */
+        if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_1)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfig->Channel))
+        {
+          LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_1, LL_ADC_OFFSET_DISABLE);
+        }
+        if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_2)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfig->Channel))
+        {
+          LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_2, LL_ADC_OFFSET_DISABLE);
+        }
+        if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_3)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfig->Channel))
+        {
+          LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_3, LL_ADC_OFFSET_DISABLE);
+        }
+        if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_4)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfig->Channel))
+        {
+          LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_4, LL_ADC_OFFSET_DISABLE);
+        }
+      }
+    }
+
+    /* Parameters update conditioned to ADC state:                              */
+    /* Parameters that can be updated only when ADC is disabled:                */
+    /*  - Single or differential mode                                           */
+    /*  - Internal measurement channels: Vbat/VrefInt/TempSensor                */
+    if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+    {
+      /* Set mode single-ended or differential input of the selected ADC channel */
+      LL_ADC_SetChannelSingleDiff(hadc->Instance, sConfig->Channel, sConfig->SingleDiff);
+
+      /* Configuration of differential mode */
+      if (sConfig->SingleDiff == ADC_DIFFERENTIAL_ENDED)
+      {
+        /* Set sampling time of the selected ADC channel */
+        /* Note: ADC channel number masked with value "0x1F" to ensure shift value within 32 bits range */
+        LL_ADC_SetChannelSamplingTime(hadc->Instance,
+                                      (uint32_t)(__LL_ADC_DECIMAL_NB_TO_CHANNEL((__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfig->Channel) + 1UL) & 0x1FUL)),
+                                      sConfig->SamplingTime);
+      }
+
+      /* Management of internal measurement channels: Vbat/VrefInt/TempSensor.  */
+      /* If internal channel selected, enable dedicated internal buffers and    */
+      /* paths.                                                                 */
+      /* Note: these internal measurement paths can be disabled using           */
+      /* HAL_ADC_DeInit().                                                      */
+
+      if(__LL_ADC_IS_CHANNEL_INTERNAL(sConfig->Channel))
+      {
+        /* Configuration of common ADC parameters                                 */
+
+        tmp_config_internal_channel = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+        /* Software is allowed to change common parameters only when all ADCs   */
+        /* of the common group are disabled.                                    */
+        if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+        {
+          /* If the requested internal measurement path has already been enabled, */
+          /* bypass the configuration processing.                                 */
+          if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_TEMPSENSOR) == 0UL))
+          {
+            if (ADC_TEMPERATURE_SENSOR_INSTANCE(hadc))
+            {
+              LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_TEMPSENSOR | tmp_config_internal_channel);
+
+              /* Delay for temperature sensor stabilization time */
+              /* Wait loop initialization and execution */
+              /* Note: Variable divided by 2 to compensate partially              */
+              /*       CPU processing cycles, scaling in us split to not          */
+              /*       exceed 32 bits register capacity and handle low frequency. */
+              wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
+              while(wait_loop_index != 0UL)
+              {
+                wait_loop_index--;
+              }
+            }
+          }
+          else if ((sConfig->Channel == ADC_CHANNEL_VBAT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VBAT) == 0UL))
+          {
+            if (ADC_BATTERY_VOLTAGE_INSTANCE(hadc))
+            {
+              LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VBAT | tmp_config_internal_channel);
+            }
+          }
+          else if ((sConfig->Channel == ADC_CHANNEL_VREFINT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VREFINT) == 0UL))
+          {
+            if (ADC_VREFINT_INSTANCE(hadc))
+            {
+              LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VREFINT | tmp_config_internal_channel);
+            }
+          }
+          else
+          {
+            /* nothing to do */
+          }
+        }
+        /* If the requested internal measurement path has already been          */
+        /* enabled and other ADC of the common group are enabled, internal      */
+        /* measurement paths cannot be enabled.                                 */
+        else
+        {
+          /* Update ADC state machine to error */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+          tmp_hal_status = HAL_ERROR;
+        }
+      }
+    }
+  }
+
+  /* If a conversion is on going on regular group, no update on regular       */
+  /* channel could be done on neither of the channel configuration structure  */
+  /* parameters.                                                              */
+  else
+  {
+    /* Update ADC state machine to error */
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Configure the analog watchdog.
+  * @note   Possibility to update parameters on the fly:
+  *         This function initializes the selected analog watchdog, successive
+  *         calls to this function can be used to reconfigure some parameters
+  *         of structure "ADC_AnalogWDGConfTypeDef" on the fly, without resetting
+  *         the ADC.
+  *         The setting of these parameters is conditioned to ADC state.
+  *         For parameters constraints, see comments of structure
+  *         "ADC_AnalogWDGConfTypeDef".
+  * @note   On this STM32 series, analog watchdog thresholds cannot be modified
+  *         while ADC conversion is on going.
+  * @param hadc ADC handle
+  * @param AnalogWDGConfig Structure of ADC analog watchdog configuration
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef *hadc, const ADC_AnalogWDGConfTypeDef *AnalogWDGConfig)
+{
+  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+  uint32_t tmpAWDHighThresholdShifted;
+  uint32_t tmpAWDLowThresholdShifted;
+#if !defined(ADC_SUPPORT_2_5_MSPS)
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+#endif /* !ADC_SUPPORT_2_5_MSPS */
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_ANALOG_WATCHDOG_NUMBER(AnalogWDGConfig->WatchdogNumber));
+  assert_param(IS_ADC_ANALOG_WATCHDOG_MODE(AnalogWDGConfig->WatchdogMode));
+  assert_param(IS_FUNCTIONAL_STATE(AnalogWDGConfig->ITMode));
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  if(AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REG)
+#else
+  if ((AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REG)     ||
+      (AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_INJEC)   ||
+      (AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REGINJEC))
+#endif /* ADC_SUPPORT_2_5_MSPS */
+  {
+    assert_param(IS_ADC_CHANNEL(hadc, AnalogWDGConfig->Channel));
+  }
+
+  /* Verify thresholds range */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+  /* Verify if thresholds are within the selected ADC resolution */
+  assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->HighThreshold));
+  assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->LowThreshold));
+#else
+  if (hadc->Init.OversamplingMode == ENABLE)
+  {
+    /* Case of oversampling enabled: depending on ratio and shift configuration,
+       analog watchdog thresholds can be higher than ADC resolution.
+       Verify if thresholds are within maximum thresholds range. */
+    assert_param(IS_ADC_RANGE(ADC_RESOLUTION_12B, AnalogWDGConfig->HighThreshold));
+    assert_param(IS_ADC_RANGE(ADC_RESOLUTION_12B, AnalogWDGConfig->LowThreshold));
+  }
+  else
+  {
+    /* Verify if thresholds are within the selected ADC resolution */
+    assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->HighThreshold));
+    assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), AnalogWDGConfig->LowThreshold));
+  }
+#endif
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* Parameters update conditioned to ADC state:                              */
+  /* Parameters that can be updated when ADC is disabled or enabled without   */
+  /* conversion on going on ADC groups regular and injected:                  */
+  /*  - Analog watchdog channels                                              */
+  /*  - Analog watchdog thresholds                                            */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+#else
+  tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+  tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+  if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+      && (tmp_adc_is_conversion_on_going_injected == 0UL)
+     )
+#endif /* ADC_SUPPORT_2_5_MSPS */
+  {
+    /* Analog watchdog configuration */
+    if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_1)
+    {
+      /* Configuration of analog watchdog:                                    */
+      /*  - Set the analog watchdog enable mode: one or overall group of      */
+      /*    channels, on groups regular and-or injected.                      */
+      switch (AnalogWDGConfig->WatchdogMode)
+      {
+        case ADC_ANALOGWATCHDOG_SINGLE_REG:
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, __LL_ADC_ANALOGWD_CHANNEL_GROUP(AnalogWDGConfig->Channel,
+                                          LL_ADC_GROUP_REGULAR));
+          break;
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+        case ADC_ANALOGWATCHDOG_SINGLE_INJEC:
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, __LL_ADC_ANALOGWD_CHANNEL_GROUP(AnalogWDGConfig->Channel,
+                                          LL_ADC_GROUP_INJECTED));
+          break;
+
+        case ADC_ANALOGWATCHDOG_SINGLE_REGINJEC:
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, __LL_ADC_ANALOGWD_CHANNEL_GROUP(AnalogWDGConfig->Channel,
+                                          LL_ADC_GROUP_REGULAR_INJECTED));
+          break;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+        case ADC_ANALOGWATCHDOG_ALL_REG:
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_ALL_CHANNELS_REG);
+          break;
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+        case ADC_ANALOGWATCHDOG_ALL_INJEC:
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_ALL_CHANNELS_INJ);
+          break;
+
+        case ADC_ANALOGWATCHDOG_ALL_REGINJEC:
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_ALL_CHANNELS_REG_INJ);
+          break;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+        default: /* ADC_ANALOGWATCHDOG_NONE */
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, LL_ADC_AWD1, LL_ADC_AWD_DISABLE);
+          break;
+      }
+
+      /* Shift the offset in function of the selected ADC resolution:         */
+      /* Thresholds have to be left-aligned on bit 11, the LSB (right bits)   */
+      /* are set to 0                                                         */
+      tmpAWDHighThresholdShifted = ADC_AWD1THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->HighThreshold);
+      tmpAWDLowThresholdShifted  = ADC_AWD1THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->LowThreshold);
+
+      /* Set ADC analog watchdog thresholds value of both thresholds high and low */
+      LL_ADC_ConfigAnalogWDThresholds(hadc->Instance, AnalogWDGConfig->WatchdogNumber, tmpAWDHighThresholdShifted, tmpAWDLowThresholdShifted);
+
+      /* Update state, clear previous result related to AWD1 */
+      CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+      /* Clear flag ADC analog watchdog */
+      /* Note: Flag cleared Clear the ADC Analog watchdog flag to be ready  */
+      /* to use for HAL_ADC_IRQHandler() or HAL_ADC_PollForEvent()          */
+      /* (in case left enabled by previous ADC operations).                 */
+      LL_ADC_ClearFlag_AWD1(hadc->Instance);
+
+      /* Configure ADC analog watchdog interrupt */
+      if (AnalogWDGConfig->ITMode == ENABLE)
+      {
+        LL_ADC_EnableIT_AWD1(hadc->Instance);
+      }
+      else
+      {
+        LL_ADC_DisableIT_AWD1(hadc->Instance);
+      }
+    }
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    /* Feature "ADC analog watchdog 2 and 3" not available on ADC peripheral of this STM32WB device */
+#else
+    /* Case of ADC_ANALOGWATCHDOG_2 or ADC_ANALOGWATCHDOG_3 */
+    else
+    {
+      switch (AnalogWDGConfig->WatchdogMode)
+      {
+        case ADC_ANALOGWATCHDOG_SINGLE_REG:
+#if !defined(ADC_SUPPORT_2_5_MSPS)
+        case ADC_ANALOGWATCHDOG_SINGLE_INJEC:
+        case ADC_ANALOGWATCHDOG_SINGLE_REGINJEC:
+#endif /* !ADC_SUPPORT_2_5_MSPS */
+          /* Update AWD by bitfield to keep the possibility to monitor        */
+          /* several channels by successive calls of this function.           */
+          if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+          {
+            SET_BIT(hadc->Instance->AWD2CR, (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(AnalogWDGConfig->Channel) & 0x1FUL)));
+          }
+          else
+          {
+            SET_BIT(hadc->Instance->AWD3CR, (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB(AnalogWDGConfig->Channel) & 0x1FUL)));
+          }
+          break;
+
+        case ADC_ANALOGWATCHDOG_ALL_REG:
+#if !defined(ADC_SUPPORT_2_5_MSPS)
+        case ADC_ANALOGWATCHDOG_ALL_INJEC:
+        case ADC_ANALOGWATCHDOG_ALL_REGINJEC:
+#endif /* !ADC_SUPPORT_2_5_MSPS */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, AnalogWDGConfig->WatchdogNumber, LL_ADC_AWD_ALL_CHANNELS_REG);
+#else
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, AnalogWDGConfig->WatchdogNumber, LL_ADC_AWD_ALL_CHANNELS_REG_INJ);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+          break;
+
+        default: /* ADC_ANALOGWATCHDOG_NONE */
+          LL_ADC_SetAnalogWDMonitChannels(hadc->Instance, AnalogWDGConfig->WatchdogNumber, LL_ADC_AWD_DISABLE);
+          break;
+      }
+
+      /* Shift the thresholds in function of the selected ADC resolution      */
+      /* have to be left-aligned on bit 7, the LSB (right bits) are set to 0  */
+      tmpAWDHighThresholdShifted = ADC_AWD23THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->HighThreshold);
+      tmpAWDLowThresholdShifted  = ADC_AWD23THRESHOLD_SHIFT_RESOLUTION(hadc, AnalogWDGConfig->LowThreshold);
+
+      /* Set ADC analog watchdog thresholds value of both thresholds high and low */
+      LL_ADC_ConfigAnalogWDThresholds(hadc->Instance, AnalogWDGConfig->WatchdogNumber, tmpAWDHighThresholdShifted, tmpAWDLowThresholdShifted);
+
+      if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+      {
+        /* Update state, clear previous result related to AWD2 */
+        CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+        /* Clear flag ADC analog watchdog */
+        /* Note: Flag cleared Clear the ADC Analog watchdog flag to be ready  */
+        /* to use for HAL_ADC_IRQHandler() or HAL_ADC_PollForEvent()          */
+        /* (in case left enabled by previous ADC operations).                 */
+        LL_ADC_ClearFlag_AWD2(hadc->Instance);
+
+        /* Configure ADC analog watchdog interrupt */
+        if (AnalogWDGConfig->ITMode == ENABLE)
+        {
+          LL_ADC_EnableIT_AWD2(hadc->Instance);
+        }
+        else
+        {
+          LL_ADC_DisableIT_AWD2(hadc->Instance);
+        }
+      }
+      /* (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_3) */
+      else
+      {
+        /* Update state, clear previous result related to AWD3 */
+        CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+        /* Clear flag ADC analog watchdog */
+        /* Note: Flag cleared Clear the ADC Analog watchdog flag to be ready  */
+        /* to use for HAL_ADC_IRQHandler() or HAL_ADC_PollForEvent()          */
+        /* (in case left enabled by previous ADC operations).                 */
+        LL_ADC_ClearFlag_AWD3(hadc->Instance);
+
+        /* Configure ADC analog watchdog interrupt */
+        if (AnalogWDGConfig->ITMode == ENABLE)
+        {
+          LL_ADC_EnableIT_AWD3(hadc->Instance);
+        }
+        else
+        {
+          LL_ADC_DisableIT_AWD3(hadc->Instance);
+        }
+      }
+    }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  }
+  /* If a conversion is on going on ADC group regular or injected, no update  */
+  /* could be done on neither of the AWD configuration structure parameters.  */
+  else
+  {
+    /* Update ADC state machine to error */
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+    tmp_hal_status = HAL_ERROR;
+  }
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+
+/**
+  * @}
+  */
+
+/** @defgroup ADC_Exported_Functions_Group4 Peripheral State functions
+  *  @brief    ADC Peripheral State functions
+  *
+@verbatim
+ ===============================================================================
+            ##### Peripheral state and errors functions #####
+ ===============================================================================
+    [..]
+    This subsection provides functions to get in run-time the status of the
+    peripheral.
+      (+) Check the ADC state
+      (+) Check the ADC error code
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the ADC handle state.
+  * @note   ADC state machine is managed by bitfields, ADC status must be
+  *         compared with states bits.
+  *         For example:
+  *           " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_REG_BUSY) != 0UL) "
+  *           " if ((HAL_ADC_GetState(hadc1) & HAL_ADC_STATE_AWD1) != 0UL) "
+  * @param hadc ADC handle
+  * @retval ADC handle state (bitfield on 32 bits)
+  */
+uint32_t HAL_ADC_GetState(const ADC_HandleTypeDef *hadc)
+{
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Return ADC handle state */
+  return hadc->State;
+}
+
+/**
+  * @brief  Return the ADC error code.
+  * @param hadc ADC handle
+  * @retval ADC error code (bitfield on 32 bits)
+  */
+uint32_t HAL_ADC_GetError(const ADC_HandleTypeDef *hadc)
+{
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  return hadc->ErrorCode;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup ADC_Private_Functions ADC Private Functions
+  * @{
+  */
+
+/**
+  * @brief  Stop ADC conversion.
+  * @param hadc ADC handle
+  * @param ConversionGroup ADC group regular and/or injected.
+  *          This parameter can be one of the following values:
+  *            @arg @ref ADC_REGULAR_GROUP               ADC regular conversion type.
+  *            @arg @ref ADC_INJECTED_GROUP         (1)  ADC injected conversion type.
+  *            @arg @ref ADC_REGULAR_INJECTED_GROUP (1)  ADC regular and injected conversion type.
+  *
+  *         (1) On STM32WB series, parameter not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx.
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef ADC_ConversionStop(ADC_HandleTypeDef *hadc, uint32_t ConversionGroup)
+{
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+  UNUSED(ConversionGroup);
+  
+  uint32_t tickstart;
+  
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  
+  /* Verification if ADC is not already stopped on regular group to bypass    */
+  /* this function if not needed.                                             */
+  if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL)
+  {
+    /* Stop potential conversion on going on regular group */
+    /* Software is allowed to set ADSTP only when ADSTART=1 and ADDIS=0 */
+    if (LL_ADC_IsDisableOngoing(hadc->Instance) == 0UL)
+    {
+      /* Stop ADC group regular conversion */
+      LL_ADC_REG_StopConversion(hadc->Instance);
+    }
+    
+    /* Wait for conversion effectively stopped */
+    /* Get tick count */
+    tickstart = HAL_GetTick();
+    
+    while((hadc->Instance->CR & ADC_CR_ADSTART) != 0UL)
+    {
+      if((HAL_GetTick() - tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+      {
+        /* Update ADC state machine to error */
+        SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+      
+        /* Set ADC error code to ADC peripheral internal error */
+        SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+        
+        return HAL_ERROR;
+      }
+    }
+    
+  }
+#else
+  uint32_t tickstart;
+  uint32_t Conversion_Timeout_CPU_cycles = 0UL;
+  uint32_t conversion_group_reassigned = ConversionGroup;
+  uint32_t tmp_ADC_CR_ADSTART_JADSTART;
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_CONVERSION_GROUP(ConversionGroup));
+
+  /* Verification if ADC is not already stopped (on regular and injected      */
+  /* groups) to bypass this function if not needed.                           */
+  tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+  tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+  if ((tmp_adc_is_conversion_on_going_regular != 0UL)
+      || (tmp_adc_is_conversion_on_going_injected != 0UL)
+     )
+  {
+    /* Particular case of continuous auto-injection mode combined with        */
+    /* auto-delay mode.                                                       */
+    /* In auto-injection mode, regular group stop ADC_CR_ADSTP is used (not   */
+    /* injected group stop ADC_CR_JADSTP).                                    */
+    /* Procedure to be followed: Wait until JEOS=1, clear JEOS, set ADSTP=1   */
+    /* (see reference manual).                                                */
+    if (((hadc->Instance->CFGR & ADC_CFGR_JAUTO) != 0UL)
+        && (hadc->Init.ContinuousConvMode == ENABLE)
+        && (hadc->Init.LowPowerAutoWait == ENABLE)
+       )
+    {
+      /* Use stop of regular group */
+      conversion_group_reassigned = ADC_REGULAR_GROUP;
+
+      /* Wait until JEOS=1 (maximum Timeout: 4 injected conversions) */
+      while (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS) == 0UL)
+      {
+        if (Conversion_Timeout_CPU_cycles >= (ADC_CONVERSION_TIME_MAX_CPU_CYCLES * 4UL))
+        {
+          /* Update ADC state machine to error */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+          /* Set ADC error code to ADC peripheral internal error */
+          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+          return HAL_ERROR;
+        }
+        Conversion_Timeout_CPU_cycles ++;
+      }
+
+      /* Clear JEOS */
+      __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOS);
+    }
+
+    /* Stop potential conversion on going on ADC group regular */
+    if (conversion_group_reassigned != ADC_INJECTED_GROUP)
+    {
+      /* Software is allowed to set ADSTP only when ADSTART=1 and ADDIS=0 */
+      if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL)
+      {
+        if (LL_ADC_IsDisableOngoing(hadc->Instance) == 0UL)
+        {
+          /* Stop ADC group regular conversion */
+          LL_ADC_REG_StopConversion(hadc->Instance);
+        }
+      }
+    }
+
+    /* Stop potential conversion on going on ADC group injected */
+    if (conversion_group_reassigned != ADC_REGULAR_GROUP)
+    {
+      /* Software is allowed to set JADSTP only when JADSTART=1 and ADDIS=0 */
+      if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) != 0UL)
+      {
+        if (LL_ADC_IsDisableOngoing(hadc->Instance) == 0UL)
+        {
+          /* Stop ADC group injected conversion */
+          LL_ADC_INJ_StopConversion(hadc->Instance);
+        }
+      }
+    }
+
+    /* Selection of start and stop bits with respect to the regular or injected group */
+    switch (conversion_group_reassigned)
+    {
+      case ADC_REGULAR_INJECTED_GROUP:
+        tmp_ADC_CR_ADSTART_JADSTART = (ADC_CR_ADSTART | ADC_CR_JADSTART);
+        break;
+      case ADC_INJECTED_GROUP:
+        tmp_ADC_CR_ADSTART_JADSTART = ADC_CR_JADSTART;
+        break;
+      /* Case ADC_REGULAR_GROUP only*/
+      default:
+        tmp_ADC_CR_ADSTART_JADSTART = ADC_CR_ADSTART;
+        break;
+    }
+
+    /* Wait for conversion effectively stopped */
+    tickstart = HAL_GetTick();
+
+    while ((hadc->Instance->CR & tmp_ADC_CR_ADSTART_JADSTART) != 0UL)
+    {
+      if ((HAL_GetTick() - tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+      {
+        /* New check to avoid false timeout detection in case of preemption */
+        if ((hadc->Instance->CR & tmp_ADC_CR_ADSTART_JADSTART) != 0UL)
+        {
+          /* Update ADC state machine to error */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+          /* Set ADC error code to ADC peripheral internal error */
+          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+          return HAL_ERROR;
+        }
+      }
+    }
+
+  }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Return HAL status */
+  return HAL_OK;
+}
+
+
+
+/**
+  * @brief  Enable the selected ADC.
+  * @note   Prerequisite condition to use this function: ADC must be disabled
+  *         and voltage regulator must be enabled (done into HAL_ADC_Init()).
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef *hadc)
+{
+  uint32_t tickstart;
+  __IO uint32_t wait_loop_index = 0UL;
+
+  /* ADC enable and wait for ADC ready (in case of ADC is disabled or         */
+  /* enabling phase not yet completed: flag ADC ready not yet set).           */
+  /* Timeout implemented to not be stuck if ADC cannot be enabled (possible   */
+  /* causes: ADC clock not running, ...).                                     */
+  if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+  {
+    /* Check if conditions to enable the ADC are fulfilled */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    if ((hadc->Instance->CR & (ADC_CR_ADCAL | ADC_CR_ADSTP | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN)) != 0UL)
+#else
+    if ((hadc->Instance->CR & (ADC_CR_ADCAL | ADC_CR_JADSTP | ADC_CR_ADSTP | ADC_CR_JADSTART | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN)) != 0UL)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    {
+      /* Update ADC state machine to error */
+      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+      /* Set ADC error code to ADC peripheral internal error */
+      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+      return HAL_ERROR;
+    }
+
+    /* Enable the ADC peripheral */
+    LL_ADC_Enable(hadc->Instance);
+
+    if((LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) & LL_ADC_PATH_INTERNAL_TEMPSENSOR) != 0UL)
+    {
+      /* Delay for temperature sensor buffer stabilization time */
+      /* Wait loop initialization and execution */
+      /* Note: Variable divided by 2 to compensate partially              */
+      /*       CPU processing cycles, scaling in us split to not          */
+      /*       exceed 32 bits register capacity and handle low frequency. */
+      wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_BUFFER_STAB_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
+      while(wait_loop_index != 0UL)
+      {
+        wait_loop_index--;
+      }
+    }
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+    /* If low power mode AutoPowerOff is enabled, power-on/off phases are     */
+    /* performed automatically by hardware and flag ADC ready is not set.     */
+    if (hadc->Init.LowPowerAutoPowerOff != ENABLE)
+#endif /*ADC_SUPPORT_2_5_MSPS */
+    {
+      /* Wait for ADC effectively enabled */
+      tickstart = HAL_GetTick();
+      
+      while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)
+      {
+        /*  If ADEN bit is set less than 4 ADC clock cycles after the ADCAL bit 
+            has been cleared (after a calibration), ADEN bit is reset by the 
+            calibration logic.
+            The workaround is to continue setting ADEN until ADRDY is becomes 1.
+            Additionally, ADC_ENABLE_TIMEOUT is defined to encompass this
+            4 ADC clock cycle duration */
+        /* Note: Test of ADC enabled required due to hardware constraint to     */
+        /*       not enable ADC if already enabled.                             */
+        if(LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+        {
+          LL_ADC_Enable(hadc->Instance);
+        }
+        
+        if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
+        {
+          /* Update ADC state machine to error */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+          
+          /* Set ADC error code to ADC peripheral internal error */
+          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+          
+          return HAL_ERROR;
+        }
+      }
+    }
+  }
+
+  /* Return HAL status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Disable the selected ADC.
+  * @note   Prerequisite condition to use this function: ADC conversions must be
+  *         stopped.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef ADC_Disable(ADC_HandleTypeDef *hadc)
+{
+  uint32_t tickstart;
+  const uint32_t tmp_adc_is_disable_on_going = LL_ADC_IsDisableOngoing(hadc->Instance);
+
+  /* Verification if ADC is not already disabled:                             */
+  /* Note: forbidden to disable ADC (set bit ADC_CR_ADDIS) if ADC is already  */
+  /*       disabled.                                                          */
+  if ((LL_ADC_IsEnabled(hadc->Instance) != 0UL)
+      && (tmp_adc_is_disable_on_going == 0UL)
+     )
+  {
+    /* Check if conditions to disable the ADC are fulfilled */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    if ((hadc->Instance->CR & (ADC_CR_ADSTART | ADC_CR_ADEN)) == ADC_CR_ADEN)
+#else
+    if ((hadc->Instance->CR & (ADC_CR_JADSTART | ADC_CR_ADSTART | ADC_CR_ADEN)) == ADC_CR_ADEN)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+    {
+      /* Disable the ADC peripheral */
+      LL_ADC_Disable(hadc->Instance);
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOSMP | ADC_FLAG_RDY));
+    }
+    else
+    {
+      /* Update ADC state machine to error */
+      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+      /* Set ADC error code to ADC peripheral internal error */
+      SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+      return HAL_ERROR;
+    }
+
+    /* Wait for ADC effectively disabled */
+    /* Get tick count */
+    tickstart = HAL_GetTick();
+
+    while ((hadc->Instance->CR & ADC_CR_ADEN) != 0UL)
+    {
+      if ((HAL_GetTick() - tickstart) > ADC_DISABLE_TIMEOUT)
+      {
+        /* New check to avoid false timeout detection in case of preemption */
+        if ((hadc->Instance->CR & ADC_CR_ADEN) != 0UL)
+        {
+          /* Update ADC state machine to error */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+          /* Set ADC error code to ADC peripheral internal error */
+          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+          return HAL_ERROR;
+        }
+      }
+    }
+  }
+
+  /* Return HAL status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  DMA transfer complete callback.
+  * @param hdma pointer to DMA handle.
+  * @retval None
+  */
+void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
+{
+  /* Retrieve ADC handle corresponding to current DMA handle */
+  ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Update state machine on conversion status if not in error state */
+  if ((hadc->State & (HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA)) == 0UL)
+  {
+    /* Set ADC state */
+    SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+
+    /* Determine whether any further conversion upcoming on group regular     */
+    /* by external trigger, continuous mode or scan sequence on going         */
+    /* to disable interruption.                                               */
+    /* Is it the end of the regular sequence ? */
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+    if(   (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+       && (hadc->Init.ContinuousConvMode == DISABLE)
+      )
+    {
+      /* If End of Sequence is reached, disable interrupts */
+      if( __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS) )
+      {
+        /* Allowed to modify bits ADC_IT_EOC/ADC_IT_EOS only if bit           */
+        /* ADSTART==0 (no conversion on going)                                */
+        if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+        {
+          /* Disable ADC end of single conversion interrupt on group regular */
+          /* Note: Overrun interrupt was enabled with EOC interrupt in        */
+          /* HAL_Start_IT(), but is not disabled here because can be used     */
+          /* by overrun IRQ process below.                                    */
+          __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC | ADC_IT_EOS);
+          
+          /* Set ADC state */
+          ADC_STATE_CLR_SET(hadc->State,
+                            HAL_ADC_STATE_REG_BUSY,
+                            HAL_ADC_STATE_READY);
+        }
+        else
+        {
+          /* Change ADC state to error state */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+          
+          /* Set ADC error code to ADC peripheral internal error */
+          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+        }
+      }
+    }
+    
+#else
+    if ((hadc->Instance->ISR & ADC_FLAG_EOS) != 0UL)
+    {
+      /* Are conversions software-triggered ? */
+      if (LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance) != 0UL)
+      {
+        /* Is CONT bit set ? */
+        if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_CONT) == 0UL)
+        {
+          /* CONT bit is not set, no more conversions expected */
+          CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+          if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+          {
+            SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+          }
+        }
+      }
+    }
+    else
+    {
+      /* DMA End of Transfer interrupt was triggered but conversions sequence
+         is not over. If DMACFG is set to 0, conversions are stopped. */
+      if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMACFG) == 0UL)
+      {
+        /* DMACFG bit is not set, conversions are stopped. */
+        CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+        if ((hadc->State & HAL_ADC_STATE_INJ_BUSY) == 0UL)
+        {
+          SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+        }
+      }
+    }
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+    /* Conversion complete callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+    hadc->ConvCpltCallback(hadc);
+#else
+    HAL_ADC_ConvCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+  }
+  else /* DMA and-or internal error occurred */
+  {
+    if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) != 0UL)
+    {
+      /* Call HAL ADC Error Callback function */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+      hadc->ErrorCallback(hadc);
+#else
+      HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+    }
+    else
+    {
+      /* Call ADC DMA error callback */
+      hadc->DMA_Handle->XferErrorCallback(hdma);
+    }
+  }
+}
+
+/**
+  * @brief  DMA half transfer complete callback.
+  * @param hdma pointer to DMA handle.
+  * @retval None
+  */
+void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+  /* Retrieve ADC handle corresponding to current DMA handle */
+  ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Half conversion callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+  hadc->ConvHalfCpltCallback(hadc);
+#else
+  HAL_ADC_ConvHalfCpltCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA error callback.
+  * @param hdma pointer to DMA handle.
+  * @retval None
+  */
+void ADC_DMAError(DMA_HandleTypeDef *hdma)
+{
+  /* Retrieve ADC handle corresponding to current DMA handle */
+  ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Set ADC state */
+  SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+
+  /* Set ADC error code to DMA error */
+  SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_DMA);
+
+  /* Error callback */
+#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
+  hadc->ErrorCallback(hadc);
+#else
+  HAL_ADC_ErrorCallback(hadc);
+#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
+}
+
+/**
+  * @}
+  */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 1826 - 0
lib/adc/stm32wbxx_hal_adc_ex.c

@@ -0,0 +1,1826 @@
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_adc_ex.c
+  * @author  MCD Application Team
+  * @brief   This file provides firmware functions to manage the following
+  *          functionalities of the Analog to Digital Converter (ADC)
+  *          peripheral:
+  *           + Operation functions
+  *             ++ Start, stop, get result of conversions of ADC group injected,
+  *                using 2 possible modes: polling, interruption (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+  *             ++ Calibration
+  *               +++ ADC automatic self-calibration
+  *               +++ Calibration factors get or set
+  *           + Control functions
+  *             ++ Channels configuration on ADC group injected (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx )
+  *           + State functions
+  *             ++ ADC group injected contexts queue management (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx )
+  *          Other functions (generic functions) are available in file
+  *          "stm32wbxx_hal_adc.c".
+  ******************************************************************************
+  * @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
+  [..]
+  (@) Sections "ADC peripheral features" and "How to use this driver" are
+      available in file of generic functions "stm32wbxx_hal_adc.c".
+  [..]
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup ADCEx ADCEx
+  * @brief ADC Extended HAL module driver
+  * @{
+  */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup ADCEx_Private_Constants ADC Extended Private Constants
+  * @{
+  */
+
+#define ADC_JSQR_FIELDS  ((ADC_JSQR_JL | ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN |\
+                           ADC_JSQR_JSQ1  | ADC_JSQR_JSQ2 |\
+                           ADC_JSQR_JSQ3 | ADC_JSQR_JSQ4 ))  /*!< ADC_JSQR fields of parameters that can be updated anytime
+                                                                  once the ADC is enabled */
+
+/* Fixed timeout value for ADC calibration.                                   */
+/* Values defined to be higher than worst cases: maximum ratio between ADC    */
+/* and CPU clock frequencies.                                                 */
+/* Example of profile low frequency : ADC frequency at 46.9kHz (ADC clock     */
+/* source PLL SAI 12MHz, ADC clock prescaler 256), CPU frequency 64MHz.       */
+/* Calibration time max = 116 / fADC (refer to datasheet)                     */
+/*                      = 158 379 CPU cycles                                  */
+#define ADC_CALIBRATION_TIMEOUT         (158379UL)   /*!< ADC calibration time-out value (unit: CPU cycles) */
+#define ADC_DISABLE_TIMEOUT             (2UL)
+
+/**
+  * @}
+  */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup ADCEx_Exported_Functions ADC Extended Exported Functions
+  * @{
+  */
+
+/** @defgroup ADCEx_Exported_Functions_Group1 Extended Input and Output operation functions
+  * @brief    Extended IO operation functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### IO operation functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+
+      (+) Perform the ADC self-calibration for single or differential ending.
+      (+) Get calibration factors for single or differential ending.
+      (+) Set calibration factors for single or differential ending.
+
+      (+) Start conversion of ADC group injected (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+      (+) Stop conversion of ADC group injected (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+      (+) Poll for conversion complete on ADC group injected (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+      (+) Get result of ADC group injected channel conversion (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+      (+) Start conversion of ADC group injected and enable interruptions (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+      (+) Stop conversion of ADC group injected and disable interruptions (not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx ).
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Perform an ADC automatic self-calibration
+  *         Calibration prerequisite: ADC must be disabled (execute this
+  *         function before HAL_ADC_Start() or after HAL_ADC_Stop() ).
+  * @param  hadc       ADC handle
+  * @param  SingleDiff Selection of single-ended or differential input
+  *         This parameter can be one of the following values:
+  *           @arg @ref ADC_SINGLE_ENDED       Channel in mode input single ended
+  *           @arg @ref ADC_DIFFERENTIAL_ENDED Channel in mode input differential ended (1)
+  *
+  *         (1) On STM32WB series, parameter not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc, uint32_t SingleDiff)
+{
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  UNUSED(SingleDiff);
+
+  uint32_t calibration_index;
+  uint32_t calibration_factor_accumulated = 0;
+  uint32_t backup_setting_cfgr1;
+  uint32_t tickstart;
+  uint32_t adc_clk_async_presc;
+  __IO uint32_t delay_cpu_cycles;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  HAL_StatusTypeDef tmp_hal_status;
+  __IO uint32_t wait_loop_index = 0UL;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* Calibration prerequisite: ADC must be disabled. */
+
+  /* Disable the ADC (if not already disabled) */
+  tmp_hal_status = ADC_Disable(hadc);
+
+  /* Check if ADC is effectively disabled */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Set ADC state */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+    ADC_STATE_CLR_SET(hadc->State,
+                      HAL_ADC_STATE_REG_BUSY,
+                      HAL_ADC_STATE_BUSY_INTERNAL);
+#else
+    ADC_STATE_CLR_SET(hadc->State,
+                      HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+                      HAL_ADC_STATE_BUSY_INTERNAL);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+    /* Start ADC calibration in mode single-ended or differential */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+    /* Manage settings impacting calibration */
+    /* - Disable ADC mode auto power-off */
+    /* - Disable ADC DMA transfer request during calibration */
+    /* Note: Specificity of this STM32 series: Calibration factor is          */
+    /*       available in data register and also transferred by DMA.          */
+    /*       To not insert ADC calibration factor among ADC conversion data   */
+    /*       in array variable, DMA transfer must be disabled during          */
+    /*       calibration.                                                     */
+    backup_setting_cfgr1 = READ_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | ADC_CFGR1_AUTOFF);
+    CLEAR_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | ADC_CFGR1_AUTOFF);
+
+    /* ADC calibration procedure */
+    /* Note: Perform an averaging of 8 calibrations for optimized accuracy */
+    for (calibration_index = 0UL; calibration_index < 8UL; calibration_index++)
+    {
+      /* Start ADC calibration */
+      LL_ADC_StartCalibration(hadc->Instance);
+
+#else
+    LL_ADC_StartCalibration(hadc->Instance, SingleDiff);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+    /* Wait for calibration completion */
+    while (LL_ADC_IsCalibrationOnGoing(hadc->Instance) != 0UL)
+    {
+      wait_loop_index++;
+      if (wait_loop_index >= ADC_CALIBRATION_TIMEOUT)
+      {
+        /* Update ADC state machine to error */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_BUSY_INTERNAL,
+                          HAL_ADC_STATE_ERROR_INTERNAL);
+
+        /* Process unlocked */
+        __HAL_UNLOCK(hadc);
+
+        return HAL_ERROR;
+      }
+    }
+#if defined(ADC_SUPPORT_2_5_MSPS)
+      calibration_factor_accumulated += LL_ADC_GetCalibrationFactor(hadc->Instance);
+    }
+    /* Compute average */
+    calibration_factor_accumulated /= calibration_index;
+    /* Apply calibration factor (requires ADC enable and disable process) */
+    LL_ADC_Enable(hadc->Instance);
+
+    /* Case of ADC clocked at low frequency: Delay required between ADC enable and disable actions */
+    if(LL_ADC_GetClock(hadc->Instance) == LL_ADC_CLOCK_ASYNC)
+    {
+      adc_clk_async_presc = LL_ADC_GetCommonClock(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+      if(adc_clk_async_presc >= LL_ADC_CLOCK_ASYNC_DIV16)
+      {
+        /* Delay loop initialization and execution */
+        /* Delay depends on ADC clock prescaler: Compute ADC clock asynchronous prescaler to decimal format */
+        delay_cpu_cycles = (1U << ((adc_clk_async_presc >> ADC_CCR_PRESC_Pos) - 3U));
+        /* Divide variable by 2 to compensate partially CPU processing cycles */
+        delay_cpu_cycles >>= 1U;
+
+        while(delay_cpu_cycles != 0)
+        {
+          delay_cpu_cycles--;
+        }
+      }
+    }
+
+    LL_ADC_SetCalibrationFactor(hadc->Instance, calibration_factor_accumulated);
+    LL_ADC_Disable(hadc->Instance);
+
+    /* Wait for ADC effectively disabled before changing configuration */
+    /* Get tick count */
+    tickstart = HAL_GetTick();
+
+    while (LL_ADC_IsEnabled(hadc->Instance) != 0UL)
+    {
+      if ((HAL_GetTick() - tickstart) > ADC_DISABLE_TIMEOUT)
+      {
+        /* New check to avoid false timeout detection in case of preemption */
+        if (LL_ADC_IsEnabled(hadc->Instance) != 0UL)
+        {
+          /* Update ADC state machine to error */
+          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+          /* Set ADC error code to ADC peripheral internal error */
+          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+          return HAL_ERROR;
+        }
+      }
+    }
+
+    /* Restore configuration after calibration */
+    SET_BIT(hadc->Instance->CFGR1, backup_setting_cfgr1);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+    /* Set ADC state */
+    ADC_STATE_CLR_SET(hadc->State,
+                      HAL_ADC_STATE_BUSY_INTERNAL,
+                      HAL_ADC_STATE_READY);
+  }
+  else
+  {
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+    /* Note: No need to update variable "tmp_hal_status" here: already set    */
+    /*       to state "HAL_ERROR" by function disabling the ADC.              */
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Get the calibration factor.
+  * @param hadc ADC handle.
+  * @param SingleDiff This parameter can be only:
+  *           @arg @ref ADC_SINGLE_ENDED       Channel in mode input single ended
+  *           @arg @ref ADC_DIFFERENTIAL_ENDED Channel in mode input differential ended (1)
+  *
+  *         (1) On STM32WB series, parameter not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx.
+  * @retval Calibration value.
+  */
+uint32_t HAL_ADCEx_Calibration_GetValue(const ADC_HandleTypeDef *hadc, uint32_t SingleDiff)
+{
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  UNUSED(SingleDiff);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+  
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
+
+  /* Return the selected ADC calibration value */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  return LL_ADC_GetCalibrationFactor(hadc->Instance);
+#else
+  return LL_ADC_GetCalibrationFactor(hadc->Instance, SingleDiff);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+}
+
+/**
+  * @brief  Set the calibration factor to overwrite automatic conversion result.
+  *         ADC must be enabled and no conversion is ongoing.
+  * @param hadc ADC handle
+  * @param SingleDiff This parameter can be only:
+  *           @arg @ref ADC_SINGLE_ENDED       Channel in mode input single ended
+  *           @arg @ref ADC_DIFFERENTIAL_ENDED Channel in mode input differential ended (1)
+  *
+  *         (1) On STM32WB series, parameter not available on devices: STM32WB10xx, STM32WB15xx, STM32WB1Mxx.
+  * @param CalibrationFactor Calibration factor (coded on 7 bits maximum)
+  * @retval HAL state
+  */
+HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef *hadc, uint32_t SingleDiff, uint32_t CalibrationFactor)
+{
+#if defined(ADC_SUPPORT_2_5_MSPS)
+  UNUSED(SingleDiff);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
+  assert_param(IS_ADC_CALFACT(CalibrationFactor));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* Verification of hardware constraints before modifying the calibration    */
+  /* factors register: ADC must be enabled, no conversion on going.           */
+  tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+  tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+  if ((LL_ADC_IsEnabled(hadc->Instance) != 0UL)
+      && (tmp_adc_is_conversion_on_going_regular == 0UL)
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+      && (tmp_adc_is_conversion_on_going_injected == 0UL)
+#endif /* ADC_SUPPORT_2_5_MSPS */
+     )
+  {
+    /* Set the selected ADC calibration value */
+#if defined(ADC_SUPPORT_2_5_MSPS)
+    LL_ADC_SetCalibrationFactor(hadc->Instance, CalibrationFactor);
+#else
+    LL_ADC_SetCalibrationFactor(hadc->Instance, SingleDiff, CalibrationFactor);
+#endif /* ADC_SUPPORT_2_5_MSPS */
+  }
+  else
+  {
+    /* Update ADC state machine */
+    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+    /* Update ADC error code */
+    SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+    /* Update ADC state machine to error */
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+/**
+  * @brief  Enable ADC, start conversion of injected group.
+  * @note   Interruptions enabled in this function: None.
+  * @param hadc ADC handle.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+  uint32_t tmp_config_injected_queue;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) != 0UL)
+  {
+    return HAL_BUSY;
+  }
+  else
+  {
+    /* In case of software trigger detection enabled, JQDIS must be set
+      (which can be done only if ADSTART and JADSTART are both cleared).
+       If JQDIS is not set at that point, returns an error
+       - since software trigger detection is disabled. User needs to
+       resort to HAL_ADCEx_DisableInjectedQueue() API to set JQDIS.
+       - or (if JQDIS is intentionally reset) since JEXTEN = 0 which means
+         the queue is empty */
+    tmp_config_injected_queue = READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+    if ((READ_BIT(hadc->Instance->JSQR, ADC_JSQR_JEXTEN) == 0UL)
+        && (tmp_config_injected_queue == 0UL)
+       )
+    {
+      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+      return HAL_ERROR;
+    }
+
+    /* Process locked */
+    __HAL_LOCK(hadc);
+
+    /* Enable the ADC peripheral */
+    tmp_hal_status = ADC_Enable(hadc);
+
+    /* Start conversion if ADC is effectively enabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Check if a regular conversion is ongoing */
+      if ((hadc->State & HAL_ADC_STATE_REG_BUSY) != 0UL)
+      {
+        /* Reset ADC error code field related to injected conversions only */
+        CLEAR_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+      }
+      else
+      {
+        /* Set ADC error code to none */
+        ADC_CLEAR_ERRORCODE(hadc);
+      }
+
+      /* Set ADC state                                                        */
+      /* - Clear state bitfield related to injected group conversion results  */
+      /* - Set state bitfield related to injected operation                   */
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC,
+                        HAL_ADC_STATE_INJ_BUSY);
+
+      /* Clear ADC group injected group conversion flag */
+      /* (To ensure of no unknown state from potential previous ADC operations) */
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JEOC | ADC_FLAG_JEOS));
+
+      /* Process unlocked */
+      /* Unlock before starting ADC conversions: in case of potential         */
+      /* interruption, to let the process to ADC IRQ Handler.                 */
+      __HAL_UNLOCK(hadc);
+
+      /* Enable conversion of injected group, if automatic injected conversion  */
+      /* is disabled.                                                           */
+      /* If software start has been selected, conversion starts immediately.    */
+      /* If external trigger has been selected, conversion will start at next   */
+      /* trigger event.                                                         */
+      if(LL_ADC_INJ_GetTrigAuto(hadc->Instance) == LL_ADC_INJ_TRIG_INDEPENDENT)
+      {
+        /* Start ADC group injected conversion */
+        LL_ADC_INJ_StartConversion(hadc->Instance);
+      }
+    }
+    else
+    {
+      /* Process unlocked */
+      __HAL_UNLOCK(hadc);
+    }
+
+    /* Return function status */
+    return tmp_hal_status;
+  }
+}
+
+/**
+  * @brief  Stop conversion of injected channels. Disable ADC peripheral if
+  *         no regular conversion is on going.
+  * @note   If ADC must be disabled and if conversion is on going on
+  *         regular group, function HAL_ADC_Stop must be used to stop both
+  *         injected and regular groups, and disable the ADC.
+  * @note   If injected group mode auto-injection is enabled,
+  *         function HAL_ADC_Stop must be used.
+  * @param hadc ADC handle.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* 1. Stop potential conversion on going on injected group only. */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_INJECTED_GROUP);
+
+  /* Disable ADC peripheral if injected conversions are effectively stopped   */
+  /* and if no conversion on regular group is on-going                       */
+  if (tmp_hal_status == HAL_OK)
+  {
+    if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+    {
+      /* 2. Disable the ADC peripheral */
+      tmp_hal_status = ADC_Disable(hadc);
+
+      /* Check if ADC is effectively disabled */
+      if (tmp_hal_status == HAL_OK)
+      {
+        /* Set ADC state */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+                          HAL_ADC_STATE_READY);
+      }
+    }
+    /* Conversion on injected group is stopped, but ADC not disabled since    */
+    /* conversion on regular group is still running.                          */
+    else
+    {
+      /* Set ADC state */
+      CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Wait for injected group conversion to be completed.
+  * @param hadc ADC handle
+  * @param Timeout Timeout value in millisecond.
+  * @note   Depending on hadc->Init.EOCSelection, JEOS or JEOC is
+  *         checked and cleared depending on AUTDLY bit status.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
+{
+  uint32_t tickstart;
+  uint32_t tmp_Flag_End;
+  uint32_t tmp_adc_inj_is_trigger_source_sw_start;
+  uint32_t tmp_adc_reg_is_trigger_source_sw_start;
+  uint32_t tmp_cfgr;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* If end of sequence selected */
+  if (hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV)
+  {
+    tmp_Flag_End = ADC_FLAG_JEOS;
+  }
+  else /* end of conversion selected */
+  {
+    tmp_Flag_End = ADC_FLAG_JEOC;
+  }
+
+  /* Get timeout */
+  tickstart = HAL_GetTick();
+
+  /* Wait until End of Conversion or Sequence flag is raised */
+  while ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
+  {
+    /* Check if timeout is disabled (set to infinite wait) */
+    if (Timeout != HAL_MAX_DELAY)
+    {
+      if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
+      {
+        /* New check to avoid false timeout detection in case of preemption */
+        if ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
+        {
+          /* Update ADC state machine to timeout */
+          SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+          /* Process unlocked */
+          __HAL_UNLOCK(hadc);
+
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+
+  /* Retrieve ADC configuration */
+  tmp_adc_inj_is_trigger_source_sw_start = LL_ADC_INJ_IsTriggerSourceSWStart(hadc->Instance);
+  tmp_adc_reg_is_trigger_source_sw_start = LL_ADC_REG_IsTriggerSourceSWStart(hadc->Instance);
+  tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+
+  /* Update ADC state machine */
+  SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+
+  /* Determine whether any further conversion upcoming on group injected      */
+  /* by external trigger or by automatic injected conversion                  */
+  /* from group regular.                                                      */
+  if ((tmp_adc_inj_is_trigger_source_sw_start != 0UL)            ||
+      ((READ_BIT(tmp_cfgr, ADC_CFGR_JAUTO) == 0UL)      &&
+       ((tmp_adc_reg_is_trigger_source_sw_start != 0UL)  &&
+        (READ_BIT(tmp_cfgr, ADC_CFGR_CONT) == 0UL))))
+  {
+    /* Check whether end of sequence is reached */
+    if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS))
+    {
+      /* Particular case if injected contexts queue is enabled:             */
+      /* when the last context has been fully processed, JSQR is reset      */
+      /* by the hardware. Even if no injected conversion is planned to come */
+      /* (queue empty, triggers are ignored), it can start again            */
+      /* immediately after setting a new context (JADSTART is still set).   */
+      /* Therefore, state of HAL ADC injected group is kept to busy.        */
+      if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQM) == 0UL)
+      {
+        /* Set ADC state */
+        CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+
+        if ((hadc->State & HAL_ADC_STATE_REG_BUSY) == 0UL)
+        {
+          SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+        }
+      }
+    }
+  }
+
+  /* Clear polled flag */
+  if (tmp_Flag_End == ADC_FLAG_JEOS)
+  {
+    /* Clear end of sequence JEOS flag of injected group if low power feature */
+    /* "LowPowerAutoWait " is disabled, to not interfere with this feature.   */
+    /* For injected groups, no new conversion will start before JEOS is       */
+    /* cleared.                                                               */
+    if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_AUTDLY) == 0UL)
+    {
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JEOC | ADC_FLAG_JEOS));
+    }
+  }
+  else
+  {
+    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
+  }
+
+  /* Return API HAL status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Enable ADC, start conversion of injected group with interruption.
+  * @note   Interruptions enabled in this function according to initialization
+  *         setting : JEOC (end of conversion) or JEOS (end of sequence)
+  * @param hadc ADC handle.
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+  uint32_t tmp_config_injected_queue;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) != 0UL)
+  {
+    return HAL_BUSY;
+  }
+  else
+  {
+    /* In case of software trigger detection enabled, JQDIS must be set
+      (which can be done only if ADSTART and JADSTART are both cleared).
+       If JQDIS is not set at that point, returns an error
+       - since software trigger detection is disabled. User needs to
+       resort to HAL_ADCEx_DisableInjectedQueue() API to set JQDIS.
+       - or (if JQDIS is intentionally reset) since JEXTEN = 0 which means
+         the queue is empty */
+    tmp_config_injected_queue = READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+    if ((READ_BIT(hadc->Instance->JSQR, ADC_JSQR_JEXTEN) == 0UL)
+        && (tmp_config_injected_queue == 0UL)
+       )
+    {
+      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+      return HAL_ERROR;
+    }
+
+    /* Process locked */
+    __HAL_LOCK(hadc);
+
+    /* Enable the ADC peripheral */
+    tmp_hal_status = ADC_Enable(hadc);
+
+    /* Start conversion if ADC is effectively enabled */
+    if (tmp_hal_status == HAL_OK)
+    {
+      /* Check if a regular conversion is ongoing */
+      if ((hadc->State & HAL_ADC_STATE_REG_BUSY) != 0UL)
+      {
+        /* Reset ADC error code field related to injected conversions only */
+        CLEAR_BIT(hadc->ErrorCode, HAL_ADC_ERROR_JQOVF);
+      }
+      else
+      {
+        /* Set ADC error code to none */
+        ADC_CLEAR_ERRORCODE(hadc);
+      }
+
+      /* Set ADC state                                                        */
+      /* - Clear state bitfield related to injected group conversion results  */
+      /* - Set state bitfield related to injected operation                   */
+      ADC_STATE_CLR_SET(hadc->State,
+                        HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC,
+                        HAL_ADC_STATE_INJ_BUSY);
+
+      /* Clear ADC group injected group conversion flag */
+      /* (To ensure of no unknown state from potential previous ADC operations) */
+      __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JEOC | ADC_FLAG_JEOS));
+
+      /* Process unlocked */
+      /* Unlock before starting ADC conversions: in case of potential         */
+      /* interruption, to let the process to ADC IRQ Handler.                 */
+      __HAL_UNLOCK(hadc);
+
+      /* Enable ADC Injected context queue overflow interrupt if this feature   */
+      /* is enabled.                                                            */
+      if ((hadc->Instance->CFGR & ADC_CFGR_JQM) != 0UL)
+      {
+        __HAL_ADC_ENABLE_IT(hadc, ADC_FLAG_JQOVF);
+      }
+
+      /* Enable ADC end of conversion interrupt */
+      switch (hadc->Init.EOCSelection)
+      {
+        case ADC_EOC_SEQ_CONV:
+          __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+          __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOS);
+          break;
+        /* case ADC_EOC_SINGLE_CONV */
+        default:
+          __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOS);
+          __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
+          break;
+      }
+
+      /* Enable conversion of injected group, if automatic injected conversion  */
+      /* is disabled.                                                           */
+      /* If software start has been selected, conversion starts immediately.    */
+      /* If external trigger has been selected, conversion will start at next   */
+      /* trigger event.                                                         */
+      if(LL_ADC_INJ_GetTrigAuto(hadc->Instance) == LL_ADC_INJ_TRIG_INDEPENDENT)
+      {
+        /* Start ADC group injected conversion */
+        LL_ADC_INJ_StartConversion(hadc->Instance);
+      }
+    }
+    else
+    {
+      /* Process unlocked */
+      __HAL_UNLOCK(hadc);
+    }
+
+    /* Return function status */
+    return tmp_hal_status;
+  }
+}
+
+/**
+  * @brief  Stop conversion of injected channels, disable interruption of
+  *         end-of-conversion. Disable ADC peripheral if no regular conversion
+  *         is on going.
+  * @note   If ADC must be disabled and if conversion is on going on
+  *         regular group, function HAL_ADC_Stop must be used to stop both
+  *         injected and regular groups, and disable the ADC.
+  * @note   If injected group mode auto-injection is enabled,
+  *         function HAL_ADC_Stop must be used.
+  * @note   In case of auto-injection mode, HAL_ADC_Stop() must be used.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* 1. Stop potential conversion on going on injected group only. */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_INJECTED_GROUP);
+
+  /* Disable ADC peripheral if injected conversions are effectively stopped   */
+  /* and if no conversion on the other group (regular group) is intended to   */
+  /* continue.                                                                */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Disable ADC end of conversion interrupt for injected channels */
+    __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_JEOC | ADC_IT_JEOS | ADC_FLAG_JQOVF));
+
+    if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
+    {
+      /* 2. Disable the ADC peripheral */
+      tmp_hal_status = ADC_Disable(hadc);
+
+      /* Check if ADC is effectively disabled */
+      if (tmp_hal_status == HAL_OK)
+      {
+        /* Set ADC state */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
+                          HAL_ADC_STATE_READY);
+      }
+    }
+    /* Conversion on injected group is stopped, but ADC not disabled since    */
+    /* conversion on regular group is still running.                          */
+    else
+    {
+      /* Set ADC state */
+      CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+/**
+  * @brief  Get ADC injected group conversion result.
+  * @note   Reading register JDRx automatically clears ADC flag JEOC
+  *         (ADC group injected end of unitary conversion).
+  * @note   This function does not clear ADC flag JEOS
+  *         (ADC group injected end of sequence conversion)
+  *         Occurrence of flag JEOS rising:
+  *          - If sequencer is composed of 1 rank, flag JEOS is equivalent
+  *            to flag JEOC.
+  *          - If sequencer is composed of several ranks, during the scan
+  *            sequence flag JEOC only is raised, at the end of the scan sequence
+  *            both flags JEOC and EOS are raised.
+  *         Flag JEOS must not be cleared by this function because
+  *         it would not be compliant with low power features
+  *         (feature low power auto-wait, not available on all STM32 families).
+  *         To clear this flag, either use function:
+  *         in programming model IT: @ref HAL_ADC_IRQHandler(), in programming
+  *         model polling: @ref HAL_ADCEx_InjectedPollForConversion()
+  *         or @ref __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_JEOS).
+  * @param hadc ADC handle
+  * @param InjectedRank the converted ADC injected rank.
+  *          This parameter can be one of the following values:
+  *            @arg @ref ADC_INJECTED_RANK_1 ADC group injected rank 1
+  *            @arg @ref ADC_INJECTED_RANK_2 ADC group injected rank 2
+  *            @arg @ref ADC_INJECTED_RANK_3 ADC group injected rank 3
+  *            @arg @ref ADC_INJECTED_RANK_4 ADC group injected rank 4
+  * @retval ADC group injected conversion data
+  */
+uint32_t HAL_ADCEx_InjectedGetValue(const ADC_HandleTypeDef *hadc, uint32_t InjectedRank)
+{
+  uint32_t tmp_jdr;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_INJECTED_RANK(InjectedRank));
+
+  /* Get ADC converted value */
+  switch (InjectedRank)
+  {
+    case ADC_INJECTED_RANK_4:
+      tmp_jdr = hadc->Instance->JDR4;
+      break;
+    case ADC_INJECTED_RANK_3:
+      tmp_jdr = hadc->Instance->JDR3;
+      break;
+    case ADC_INJECTED_RANK_2:
+      tmp_jdr = hadc->Instance->JDR2;
+      break;
+    case ADC_INJECTED_RANK_1:
+    default:
+      tmp_jdr = hadc->Instance->JDR1;
+      break;
+  }
+
+  /* Return ADC converted value */
+  return tmp_jdr;
+}
+
+/**
+  * @brief  Injected conversion complete callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADCEx_InjectedConvCpltCallback must be implemented in the user file.
+  */
+}
+
+/**
+  * @brief  Injected context queue overflow callback.
+  * @note   This callback is called if injected context queue is enabled
+            (parameter "QueueInjectedContext" in injected channel configuration)
+            and if a new injected context is set when queue is full (maximum 2
+            contexts).
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADCEx_InjectedQueueOverflowCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADCEx_InjectedQueueOverflowCallback must be implemented in the user file.
+  */
+}
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+/**
+  * @brief  Analog watchdog 2 callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADCEx_LevelOutOfWindow2Callback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADCEx_LevelOutOfWindow2Callback must be implemented in the user file.
+  */
+}
+
+/**
+  * @brief  Analog watchdog 3 callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADCEx_LevelOutOfWindow3Callback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADCEx_LevelOutOfWindow3Callback must be implemented in the user file.
+  */
+}
+
+
+/**
+  * @brief  End Of Sampling callback in non-blocking mode.
+  * @param hadc ADC handle
+  * @retval None
+  */
+__weak void HAL_ADCEx_EndOfSamplingCallback(ADC_HandleTypeDef *hadc)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hadc);
+
+  /* NOTE : This function should not be modified. When the callback is needed,
+            function HAL_ADCEx_EndOfSamplingCallback must be implemented in the user file.
+  */
+}
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+/**
+  * @brief  Stop ADC conversion of regular group (and injected channels in
+  *         case of auto_injection mode), disable ADC peripheral if no
+  *         conversion is on going on injected group.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* 1. Stop potential regular conversion on going */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+  /* Disable ADC peripheral if regular conversions are effectively stopped
+     and if no injected conversions are on-going */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Clear HAL_ADC_STATE_REG_BUSY bit */
+    CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+    if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+    {
+      /* 2. Disable the ADC peripheral */
+      tmp_hal_status = ADC_Disable(hadc);
+
+      /* Check if ADC is effectively disabled */
+      if (tmp_hal_status == HAL_OK)
+      {
+        /* Set ADC state */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_INJ_BUSY,
+                          HAL_ADC_STATE_READY);
+      }
+    }
+    /* Conversion on injected group is stopped, but ADC not disabled since    */
+    /* conversion on regular group is still running.                          */
+    else
+    {
+      SET_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+
+/**
+  * @brief  Stop ADC conversion of ADC groups regular and injected,
+  *         disable interrution of end-of-conversion,
+  *         disable ADC peripheral if no conversion is on going
+  *         on injected group.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop_IT(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* 1. Stop potential regular conversion on going */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+  /* Disable ADC peripheral if conversions are effectively stopped
+    and if no injected conversion is on-going */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Clear HAL_ADC_STATE_REG_BUSY bit */
+    CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+    /* Disable all regular-related interrupts */
+    __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+    /* 2. Disable ADC peripheral if no injected conversions are on-going */
+    if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+    {
+      tmp_hal_status = ADC_Disable(hadc);
+      /* if no issue reported */
+      if (tmp_hal_status == HAL_OK)
+      {
+        /* Set ADC state */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_INJ_BUSY,
+                          HAL_ADC_STATE_READY);
+      }
+    }
+    else
+    {
+      SET_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Stop ADC conversion of regular group (and injected group in
+  *         case of auto_injection mode), disable ADC DMA transfer, disable
+  *         ADC peripheral if no conversion is on going
+  *         on injected group.
+  * @param hadc ADC handle
+  * @retval HAL status.
+  */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop_DMA(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* 1. Stop potential regular conversion on going */
+  tmp_hal_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+  /* Disable ADC peripheral if conversions are effectively stopped
+     and if no injected conversion is on-going */
+  if (tmp_hal_status == HAL_OK)
+  {
+    /* Clear HAL_ADC_STATE_REG_BUSY bit */
+    CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+    /* Disable ADC DMA (ADC DMA configuration ADC_CFGR_DMACFG is kept) */
+    CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_DMAEN);
+
+    /* Disable the DMA channel (in case of DMA in circular mode or stop while */
+    /* while DMA transfer is on going)                                        */
+    tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+    /* Check if DMA channel effectively disabled */
+    if (tmp_hal_status != HAL_OK)
+    {
+      /* Update ADC state machine to error */
+      SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
+    }
+
+    /* Disable ADC overrun interrupt */
+    __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+    /* 2. Disable the ADC peripheral */
+    /* Update "tmp_hal_status" only if DMA channel disabling passed,          */
+    /* to keep in memory a potential failing status.                          */
+    if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+    {
+      if (tmp_hal_status == HAL_OK)
+      {
+        tmp_hal_status = ADC_Disable(hadc);
+      }
+      else
+      {
+        (void)ADC_Disable(hadc);
+      }
+
+      /* Check if ADC is effectively disabled */
+      if (tmp_hal_status == HAL_OK)
+      {
+        /* Set ADC state */
+        ADC_STATE_CLR_SET(hadc->State,
+                          HAL_ADC_STATE_INJ_BUSY,
+                          HAL_ADC_STATE_READY);
+      }
+    }
+    else
+    {
+      SET_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+    }
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+/**
+  * @}
+  */
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+/** @defgroup ADCEx_Exported_Functions_Group2 ADC Extended Peripheral Control functions
+  * @brief    ADC Extended Peripheral Control functions
+  *
+@verbatim
+ ===============================================================================
+             ##### Peripheral Control functions #####
+ ===============================================================================
+    [..]  This section provides functions allowing to:
+      (+) Configure channels on injected group
+      (+) Enable or Disable Injected Queue
+      (+) Disable ADC voltage regulator
+      (+) Enter ADC deep-power-down mode
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Configure a channel to be assigned to ADC group injected.
+  * @note   Possibility to update parameters on the fly:
+  *         This function initializes injected group, following calls to this
+  *         function can be used to reconfigure some parameters of structure
+  *         "ADC_InjectionConfTypeDef" on the fly, without resetting the ADC.
+  *         The setting of these parameters is conditioned to ADC state:
+  *         Refer to comments of structure "ADC_InjectionConfTypeDef".
+  * @note   In case of usage of internal measurement channels:
+  *         Vbat/VrefInt/TempSensor.
+  *         These internal paths can be disabled using function
+  *         HAL_ADC_DeInit().
+  * @note   Caution: For Injected Context Queue use, a context must be fully
+  *         defined before start of injected conversion. All channels are configured
+  *         consecutively for the same ADC instance. Therefore, the number of calls to
+  *         HAL_ADCEx_InjectedConfigChannel() must be equal to the value of parameter
+  *         InjectedNbrOfConversion for each context.
+  *  - Example 1: If 1 context is intended to be used (or if there is no use of the
+  *    Injected Queue Context feature) and if the context contains 3 injected ranks
+  *    (InjectedNbrOfConversion = 3), HAL_ADCEx_InjectedConfigChannel() must be
+  *    called once for each channel (i.e. 3 times) before starting a conversion.
+  *    This function must not be called to configure a 4th injected channel:
+  *    it would start a new context into context queue.
+  *  - Example 2: If 2 contexts are intended to be used and each of them contains
+  *    3 injected ranks (InjectedNbrOfConversion = 3),
+  *    HAL_ADCEx_InjectedConfigChannel() must be called once for each channel and
+  *    for each context (3 channels x 2 contexts = 6 calls). Conversion can
+  *    start once the 1st context is set, that is after the first three
+  *    HAL_ADCEx_InjectedConfigChannel() calls. The 2nd context can be set on the fly.
+  * @param hadc ADC handle
+  * @param sConfigInjected Structure of ADC injected group and ADC channel for
+  *         injected group.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef *hadc, const ADC_InjectionConfTypeDef *sConfigInjected)
+{
+  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
+  uint32_t tmpOffsetShifted;
+  uint32_t tmp_config_internal_channel;
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+  __IO uint32_t wait_loop_index = 0;
+
+  uint32_t tmp_JSQR_ContextQueueBeingBuilt = 0U;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+  assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime));
+  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(sConfigInjected->InjectedSingleDiff));
+  assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv));
+  assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->QueueInjectedContext));
+  assert_param(IS_ADC_EXTTRIGINJEC_EDGE(sConfigInjected->ExternalTrigInjecConvEdge));
+  assert_param(IS_ADC_EXTTRIGINJEC(hadc, sConfigInjected->ExternalTrigInjecConv));
+  assert_param(IS_ADC_OFFSET_NUMBER(sConfigInjected->InjectedOffsetNumber));
+  assert_param(IS_ADC_RANGE(ADC_GET_RESOLUTION(hadc), sConfigInjected->InjectedOffset));
+  assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjecOversamplingMode));
+
+  if (hadc->Init.ScanConvMode != ADC_SCAN_DISABLE)
+  {
+    assert_param(IS_ADC_INJECTED_RANK(sConfigInjected->InjectedRank));
+    assert_param(IS_ADC_INJECTED_NB_CONV(sConfigInjected->InjectedNbrOfConversion));
+    assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjectedDiscontinuousConvMode));
+  }
+
+
+  /* if JOVSE is set, the value of the OFFSETy_EN bit in ADCx_OFRy register is
+     ignored (considered as reset) */
+  assert_param(!((sConfigInjected->InjectedOffsetNumber != ADC_OFFSET_NONE) && (sConfigInjected->InjecOversamplingMode == ENABLE)));
+
+  /* JDISCEN and JAUTO bits can't be set at the same time  */
+  assert_param(!((sConfigInjected->InjectedDiscontinuousConvMode == ENABLE) && (sConfigInjected->AutoInjectedConv == ENABLE)));
+
+  /*  DISCEN and JAUTO bits can't be set at the same time */
+  assert_param(!((hadc->Init.DiscontinuousConvMode == ENABLE) && (sConfigInjected->AutoInjectedConv == ENABLE)));
+
+  /* Verification of channel number */
+  if (sConfigInjected->InjectedSingleDiff != ADC_DIFFERENTIAL_ENDED)
+  {
+    assert_param(IS_ADC_CHANNEL(hadc, sConfigInjected->InjectedChannel));
+  }
+  else
+  {
+    assert_param(IS_ADC_DIFF_CHANNEL(hadc, sConfigInjected->InjectedChannel));
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hadc);
+
+  /* Configuration of injected group sequencer:                               */
+  /* Hardware constraint: Must fully define injected context register JSQR    */
+  /* before make it entering into injected sequencer queue.                   */
+  /*                                                                          */
+  /* - if scan mode is disabled:                                              */
+  /*    * Injected channels sequence length is set to 0x00: 1 channel         */
+  /*      converted (channel on injected rank 1)                              */
+  /*      Parameter "InjectedNbrOfConversion" is discarded.                   */
+  /*    * Injected context register JSQR setting is simple: register is fully */
+  /*      defined on one call of this function (for injected rank 1) and can  */
+  /*      be entered into queue directly.                                     */
+  /* - if scan mode is enabled:                                               */
+  /*    * Injected channels sequence length is set to parameter               */
+  /*      "InjectedNbrOfConversion".                                          */
+  /*    * Injected context register JSQR setting more complex: register is    */
+  /*      fully defined over successive calls of this function, for each      */
+  /*      injected channel rank. It is entered into queue only when all       */
+  /*      injected ranks have been set.                                       */
+  /*   Note: Scan mode is not present by hardware on this device, but used    */
+  /*   by software for alignment over all STM32 devices.                      */
+
+  if ((hadc->Init.ScanConvMode == ADC_SCAN_DISABLE)  ||
+      (sConfigInjected->InjectedNbrOfConversion == 1U))
+  {
+    /* Configuration of context register JSQR:                                */
+    /*  - number of ranks in injected group sequencer: fixed to 1st rank      */
+    /*    (scan mode disabled, only rank 1 used)                              */
+    /*  - external trigger to start conversion                                */
+    /*  - external trigger polarity                                           */
+    /*  - channel set to rank 1 (scan mode disabled, only rank 1 can be used) */
+
+    if (sConfigInjected->InjectedRank == ADC_INJECTED_RANK_1)
+    {
+      /* Enable external trigger if trigger selection is different of         */
+      /* software start.                                                      */
+      /* Note: This configuration keeps the hardware feature of parameter     */
+      /*       ExternalTrigInjecConvEdge "trigger edge none" equivalent to    */
+      /*       software start.                                                */
+      if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START)
+      {
+        tmp_JSQR_ContextQueueBeingBuilt = (ADC_JSQR_RK(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1)
+                                           | (sConfigInjected->ExternalTrigInjecConv & ADC_JSQR_JEXTSEL)
+                                           | sConfigInjected->ExternalTrigInjecConvEdge
+                                          );
+      }
+      else
+      {
+        tmp_JSQR_ContextQueueBeingBuilt = (ADC_JSQR_RK(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1));
+      }
+
+      MODIFY_REG(hadc->Instance->JSQR, ADC_JSQR_FIELDS, tmp_JSQR_ContextQueueBeingBuilt);
+      /* For debug and informative reasons, hadc handle saves JSQR setting */
+      hadc->InjectionConfig.ContextQueue = tmp_JSQR_ContextQueueBeingBuilt;
+
+    }
+  }
+  else
+  {
+    /* Case of scan mode enabled, several channels to set into injected group */
+    /* sequencer.                                                             */
+    /*                                                                        */
+    /* Procedure to define injected context register JSQR over successive     */
+    /* calls of this function, for each injected channel rank:                */
+    /* 1. Start new context and set parameters related to all injected        */
+    /*    channels: injected sequence length and trigger.                     */
+
+    /* if hadc->InjectionConfig.ChannelCount is equal to 0, this is the first */
+    /*   call of the context under setting                                    */
+    if (hadc->InjectionConfig.ChannelCount == 0U)
+    {
+      /* Initialize number of channels that will be configured on the context */
+      /*  being built                                                         */
+      hadc->InjectionConfig.ChannelCount = sConfigInjected->InjectedNbrOfConversion;
+      /* Handle hadc saves the context under build up over each HAL_ADCEx_InjectedConfigChannel()
+         call, this context will be written in JSQR register at the last call.
+         At this point, the context is merely reset  */
+      hadc->InjectionConfig.ContextQueue = 0x00000000U;
+
+      /* Configuration of context register JSQR:                              */
+      /*  - number of ranks in injected group sequencer                       */
+      /*  - external trigger to start conversion                              */
+      /*  - external trigger polarity                                         */
+
+      /* Enable external trigger if trigger selection is different of         */
+      /* software start.                                                      */
+      /* Note: This configuration keeps the hardware feature of parameter     */
+      /*       ExternalTrigInjecConvEdge "trigger edge none" equivalent to    */
+      /*       software start.                                                */
+      if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START)
+      {
+        tmp_JSQR_ContextQueueBeingBuilt = ((sConfigInjected->InjectedNbrOfConversion - 1U)
+                                           | (sConfigInjected->ExternalTrigInjecConv & ADC_JSQR_JEXTSEL)
+                                           | sConfigInjected->ExternalTrigInjecConvEdge
+                                          );
+      }
+      else
+      {
+        tmp_JSQR_ContextQueueBeingBuilt = ((sConfigInjected->InjectedNbrOfConversion - 1U));
+      }
+
+    }
+
+    /* 2. Continue setting of context under definition with parameter       */
+    /*    related to each channel: channel rank sequence                    */
+    /* Clear the old JSQx bits for the selected rank */
+    tmp_JSQR_ContextQueueBeingBuilt &= ~ADC_JSQR_RK(ADC_SQR3_SQ10, sConfigInjected->InjectedRank);
+
+    /* Set the JSQx bits for the selected rank */
+    tmp_JSQR_ContextQueueBeingBuilt |= ADC_JSQR_RK(sConfigInjected->InjectedChannel, sConfigInjected->InjectedRank);
+
+    /* Decrease channel count  */
+    hadc->InjectionConfig.ChannelCount--;
+
+    /* 3. tmp_JSQR_ContextQueueBeingBuilt is fully built for this HAL_ADCEx_InjectedConfigChannel()
+          call, aggregate the setting to those already built during the previous
+          HAL_ADCEx_InjectedConfigChannel() calls (for the same context of course)  */
+    hadc->InjectionConfig.ContextQueue |= tmp_JSQR_ContextQueueBeingBuilt;
+
+    /* 4. End of context setting: if this is the last channel set, then write context
+        into register JSQR and make it enter into queue                   */
+    if (hadc->InjectionConfig.ChannelCount == 0U)
+    {
+      MODIFY_REG(hadc->Instance->JSQR, ADC_JSQR_FIELDS, hadc->InjectionConfig.ContextQueue);
+    }
+  }
+
+  /* Parameters update conditioned to ADC state:                              */
+  /* Parameters that can be updated when ADC is disabled or enabled without   */
+  /* conversion on going on injected group:                                   */
+  /*  - Injected context queue: Queue disable (active context is kept) or     */
+  /*    enable (context decremented, up to 2 contexts queued)                 */
+  /*  - Injected discontinuous mode: can be enabled only if auto-injected     */
+  /*    mode is disabled.                                                     */
+  if (LL_ADC_INJ_IsConversionOngoing(hadc->Instance) == 0UL)
+  {
+    /* If auto-injected mode is disabled: no constraint                       */
+    if (sConfigInjected->AutoInjectedConv == DISABLE)
+    {
+      MODIFY_REG(hadc->Instance->CFGR,
+                 ADC_CFGR_JQM | ADC_CFGR_JDISCEN,
+                 ADC_CFGR_INJECT_CONTEXT_QUEUE((uint32_t)sConfigInjected->QueueInjectedContext)           |
+                 ADC_CFGR_INJECT_DISCCONTINUOUS((uint32_t)sConfigInjected->InjectedDiscontinuousConvMode));
+    }
+    /* If auto-injected mode is enabled: Injected discontinuous setting is    */
+    /* discarded.                                                             */
+    else
+    {
+      MODIFY_REG(hadc->Instance->CFGR,
+                 ADC_CFGR_JQM | ADC_CFGR_JDISCEN,
+                 ADC_CFGR_INJECT_CONTEXT_QUEUE((uint32_t)sConfigInjected->QueueInjectedContext));
+    }
+
+  }
+
+  /* Parameters update conditioned to ADC state:                              */
+  /* Parameters that can be updated when ADC is disabled or enabled without   */
+  /* conversion on going on regular and injected groups:                      */
+  /*  - Automatic injected conversion: can be enabled if injected group       */
+  /*    external triggers are disabled.                                       */
+  /*  - Channel sampling time                                                 */
+  /*  - Channel offset                                                        */
+  tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+  tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+  if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+      && (tmp_adc_is_conversion_on_going_injected == 0UL)
+     )
+  {
+    /* If injected group external triggers are disabled (set to injected      */
+    /* software start): no constraint                                         */
+    if ((sConfigInjected->ExternalTrigInjecConv == ADC_INJECTED_SOFTWARE_START)
+        || (sConfigInjected->ExternalTrigInjecConvEdge == ADC_EXTERNALTRIGINJECCONV_EDGE_NONE))
+    {
+      if (sConfigInjected->AutoInjectedConv == ENABLE)
+      {
+        SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO);
+      }
+      else
+      {
+        CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO);
+      }
+    }
+    /* If Automatic injected conversion was intended to be set and could not  */
+    /* due to injected group external triggers enabled, error is reported.    */
+    else
+    {
+      if (sConfigInjected->AutoInjectedConv == ENABLE)
+      {
+        /* Update ADC state machine to error */
+        SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+        tmp_hal_status = HAL_ERROR;
+      }
+      else
+      {
+        CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO);
+      }
+    }
+
+    if (sConfigInjected->InjecOversamplingMode == ENABLE)
+    {
+      assert_param(IS_ADC_OVERSAMPLING_RATIO(sConfigInjected->InjecOversampling.Ratio));
+      assert_param(IS_ADC_RIGHT_BIT_SHIFT(sConfigInjected->InjecOversampling.RightBitShift));
+
+      /*  JOVSE must be reset in case of triggered regular mode  */
+      assert_param(!(READ_BIT(hadc->Instance->CFGR2, ADC_CFGR2_ROVSE | ADC_CFGR2_TROVS) == (ADC_CFGR2_ROVSE | ADC_CFGR2_TROVS)));
+
+      /* Configuration of Injected Oversampler:                                 */
+      /*  - Oversampling Ratio                                                  */
+      /*  - Right bit shift                                                     */
+
+      /* Enable OverSampling mode */
+      MODIFY_REG(hadc->Instance->CFGR2,
+                 ADC_CFGR2_JOVSE |
+                 ADC_CFGR2_OVSR  |
+                 ADC_CFGR2_OVSS,
+                 ADC_CFGR2_JOVSE                                  |
+                 sConfigInjected->InjecOversampling.Ratio         |
+                 sConfigInjected->InjecOversampling.RightBitShift
+                );
+    }
+    else
+    {
+      /* Disable Regular OverSampling */
+      CLEAR_BIT(hadc->Instance->CFGR2, ADC_CFGR2_JOVSE);
+    }
+
+      /* Set sampling time of the selected ADC channel */
+      LL_ADC_SetChannelSamplingTime(hadc->Instance, sConfigInjected->InjectedChannel, sConfigInjected->InjectedSamplingTime);
+
+    /* Configure the offset: offset enable/disable, channel, offset value */
+
+    /* Shift the offset with respect to the selected ADC resolution. */
+    /* Offset has to be left-aligned on bit 11, the LSB (right bits) are set to 0 */
+    tmpOffsetShifted = ADC_OFFSET_SHIFT_RESOLUTION(hadc, sConfigInjected->InjectedOffset);
+
+    if (sConfigInjected->InjectedOffsetNumber != ADC_OFFSET_NONE)
+    {
+      /* Set ADC selected offset number */
+      LL_ADC_SetOffset(hadc->Instance, sConfigInjected->InjectedOffsetNumber, sConfigInjected->InjectedChannel,
+                       tmpOffsetShifted);
+
+    }
+    else
+    {
+      /* Scan each offset register to check if the selected channel is targeted. */
+      /* If this is the case, the corresponding offset number is disabled.       */
+      if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_1)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+      {
+        LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_1, LL_ADC_OFFSET_DISABLE);
+      }
+      if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_2)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+      {
+        LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_2, LL_ADC_OFFSET_DISABLE);
+      }
+      if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_3)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+      {
+        LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_3, LL_ADC_OFFSET_DISABLE);
+      }
+      if(__LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_GetOffsetChannel(hadc->Instance, LL_ADC_OFFSET_4)) == __LL_ADC_CHANNEL_TO_DECIMAL_NB(sConfigInjected->InjectedChannel))
+      {
+        LL_ADC_SetOffsetState(hadc->Instance, LL_ADC_OFFSET_4, LL_ADC_OFFSET_DISABLE);
+      }
+    }
+
+  }
+
+  /* Parameters update conditioned to ADC state:                              */
+  /* Parameters that can be updated only when ADC is disabled:                */
+  /*  - Single or differential mode                                           */
+  /*  - Internal measurement channels: Vbat/VrefInt/TempSensor                */
+  if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+  {
+    /* Set mode single-ended or differential input of the selected ADC channel */
+    LL_ADC_SetChannelSingleDiff(hadc->Instance, sConfigInjected->InjectedChannel, sConfigInjected->InjectedSingleDiff);
+
+    /* Configuration of differential mode */
+    /* Note: ADC channel number masked with value "0x1F" to ensure shift value within 32 bits range */
+    if (sConfigInjected->InjectedSingleDiff == ADC_DIFFERENTIAL_ENDED)
+    {
+      /* Set sampling time of the selected ADC channel */
+      LL_ADC_SetChannelSamplingTime(hadc->Instance, (uint32_t)(__LL_ADC_DECIMAL_NB_TO_CHANNEL((__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfigInjected->InjectedChannel) + 1UL) & 0x1FUL)), sConfigInjected->InjectedSamplingTime);
+    }
+
+    /* Management of internal measurement channels: Vbat/VrefInt/TempSensor   */
+    /* internal measurement paths enable: If internal channel selected,       */
+    /* enable dedicated internal buffers and path.                            */
+    /* Note: these internal measurement paths can be disabled using           */
+    /* HAL_ADC_DeInit().                                                      */
+
+    if(__LL_ADC_IS_CHANNEL_INTERNAL(sConfigInjected->InjectedChannel))
+    {
+      /* Configuration of common ADC parameters (continuation)                */
+      /* Software is allowed to change common parameters only when all ADCs   */
+      /* of the common group are disabled.                                    */
+      if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__LL_ADC_COMMON_INSTANCE(hadc->Instance)) == 0UL)
+      {
+        tmp_config_internal_channel = LL_ADC_GetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance));
+
+        /* If the requested internal measurement path has already been enabled, */
+        /* bypass the configuration processing.                                 */
+        if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_TEMPSENSOR) == 0UL))
+        {
+          if (ADC_TEMPERATURE_SENSOR_INSTANCE(hadc))
+          {
+            LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_TEMPSENSOR | tmp_config_internal_channel);
+
+            /* Delay for temperature sensor stabilization time */
+            /* Wait loop initialization and execution */
+            /* Note: Variable divided by 2 to compensate partially              */
+            /*       CPU processing cycles, scaling in us split to not          */
+            /*       exceed 32 bits register capacity and handle low frequency. */
+            wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL)));
+            while(wait_loop_index != 0UL)
+            {
+              wait_loop_index--;
+            }
+          }
+        }
+        else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VBAT) == 0UL))
+        {
+          if (ADC_BATTERY_VOLTAGE_INSTANCE(hadc))
+          {
+            LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VBAT | tmp_config_internal_channel);
+          }
+        }
+        else if ((sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) && ((tmp_config_internal_channel & LL_ADC_PATH_INTERNAL_VREFINT) == 0UL))
+        {
+          if (ADC_VREFINT_INSTANCE(hadc))
+          {
+            LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(hadc->Instance), LL_ADC_PATH_INTERNAL_VREFINT | tmp_config_internal_channel);
+          }
+        }
+        else
+        {
+          /* nothing to do */
+        }
+      }
+      /* If the requested internal measurement path has already been enabled  */
+      /* and other ADC of the common group are enabled, internal              */
+      /* measurement paths cannot be enabled.                                 */
+      else
+      {
+        /* Update ADC state machine to error */
+        SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+        tmp_hal_status = HAL_ERROR;
+      }
+    }
+
+  }
+
+  /* Process unlocked */
+  __HAL_UNLOCK(hadc);
+
+  /* Return function status */
+  return tmp_hal_status;
+}
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+#if  defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature "ADC group injected" not available on ADC peripheral of this STM32WB device */
+#else
+/**
+  * @brief  Enable Injected Queue
+  * @note   This function resets CFGR register JQDIS bit in order to enable the
+  *         Injected Queue. JQDIS can be written only when ADSTART and JDSTART
+  *         are both equal to 0 to ensure that no regular nor injected
+  *         conversion is ongoing.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_EnableInjectedQueue(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+  tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+  /* Parameter can be set only if no conversion is on-going */
+  if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+      && (tmp_adc_is_conversion_on_going_injected == 0UL)
+     )
+  {
+    CLEAR_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+
+    /* Update state, clear previous result related to injected queue overflow */
+    CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_JQOVF);
+
+    tmp_hal_status = HAL_OK;
+  }
+  else
+  {
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  return tmp_hal_status;
+}
+
+/**
+  * @brief  Disable Injected Queue
+  * @note   This function sets CFGR register JQDIS bit in order to disable the
+  *         Injected Queue. JQDIS can be written only when ADSTART and JDSTART
+  *         are both equal to 0 to ensure that no regular nor injected
+  *         conversion is ongoing.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_DisableInjectedQueue(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+  uint32_t tmp_adc_is_conversion_on_going_regular;
+  uint32_t tmp_adc_is_conversion_on_going_injected;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
+  tmp_adc_is_conversion_on_going_injected = LL_ADC_INJ_IsConversionOngoing(hadc->Instance);
+
+  /* Parameter can be set only if no conversion is on-going */
+  if ((tmp_adc_is_conversion_on_going_regular == 0UL)
+      && (tmp_adc_is_conversion_on_going_injected == 0UL)
+     )
+  {
+    LL_ADC_INJ_SetQueueMode(hadc->Instance, LL_ADC_INJ_QUEUE_DISABLE);
+    tmp_hal_status = HAL_OK;
+  }
+  else
+  {
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  return tmp_hal_status;
+}
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+/**
+  * @brief  Disable ADC voltage regulator.
+  * @note   Disabling voltage regulator allows to save power. This operation can
+  *         be carried out only when ADC is disabled.
+  * @note   To enable again the voltage regulator, the user is expected to
+  *         resort to HAL_ADC_Init() API.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_DisableVoltageRegulator(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Setting of this feature is conditioned to ADC state: ADC must be ADC disabled */
+  if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+  {
+    LL_ADC_DisableInternalRegulator(hadc->Instance);
+    tmp_hal_status = HAL_OK;
+  }
+  else
+  {
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  return tmp_hal_status;
+}
+
+#if defined(ADC_SUPPORT_2_5_MSPS)
+/* Feature " ADC deep power-down" not available on ADC peripheral of this STM32WB device */
+#else
+/**
+  * @brief  Enter ADC deep power-down mode
+  * @note   This mode is achieved in setting DEEPPWD bit and allows to save power
+  *         in reducing leakage currents. It is particularly interesting before
+  *         entering stop modes.
+  * @note   Setting DEEPPWD automatically clears ADVREGEN bit and disables the
+  *         ADC voltage regulator. This means that this API encompasses
+  *         HAL_ADCEx_DisableVoltageRegulator(). Additionally, the internal
+  *         calibration is lost.
+  * @note   To exit the ADC deep-power-down mode, the user is expected to
+  *         resort to HAL_ADC_Init() API as well as to relaunch a calibration
+  *         with HAL_ADCEx_Calibration_Start() API or to re-apply a previously
+  *         saved calibration factor.
+  * @param hadc ADC handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_ADCEx_EnterADCDeepPowerDownMode(ADC_HandleTypeDef *hadc)
+{
+  HAL_StatusTypeDef tmp_hal_status;
+
+  /* Check the parameters */
+  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+  /* Setting of this feature is conditioned to ADC state: ADC must be ADC disabled */
+  if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
+  {
+    LL_ADC_EnableDeepPowerDown(hadc->Instance);
+    tmp_hal_status = HAL_OK;
+  }
+  else
+  {
+    tmp_hal_status = HAL_ERROR;
+  }
+
+  return tmp_hal_status;
+}
+#endif /* ADC_SUPPORT_2_5_MSPS */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 479 - 0
lib/adc/stm32wbxx_hal_cortex.c

@@ -0,0 +1,479 @@
+/**
+  ******************************************************************************
+  * @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  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));
+
+  /* Set the Region number */
+  MPU->RNR = MPU_Init->Number;
+
+  if ((MPU_Init->Enable) != 0U)
+  {
+    /* Check the parameters */
+    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));
+
+    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);
+  }
+  else
+  {
+    MPU->RBAR = 0x00U;
+    MPU->RASR = 0x00U;
+  }
+}
+#endif /* __MPU_PRESENT */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 1118 - 0
lib/adc/stm32wbxx_hal_dma.c

@@ -0,0 +1,1118 @@
+/**
+  ******************************************************************************
+  * @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
+
+  /* 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
+
+  /* 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
+  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 */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 551 - 0
lib/adc/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 */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 720 - 0
lib/adc/stm32wbxx_hal_pwr.c

@@ -0,0 +1,720 @@
+/**
+  ******************************************************************************
+  * @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
+  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 */
+  LL_PWR_WriteReg(SCR,
+                    LL_PWR_SCR_CC2HF
+                  | LL_PWR_SCR_CBLEAF
+                  | LL_PWR_SCR_CCRPEF
+#if defined(PWR_CR3_E802A)
+                  | LL_PWR_SCR_C802AF
+                  | LL_PWR_SCR_C802WUF
+#endif
+                  | LL_PWR_SCR_CBLEWUF
+#if defined(PWR_CR5_SMPSEN)
+                  | LL_PWR_SCR_CBORHF
+                  | LL_PWR_SCR_CSMPSFBF
+#endif
+                  | LL_PWR_SCR_CWUF
+                 );
+  
+  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
+
+  /* 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 */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+

+ 1824 - 0
lib/adc/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 */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 2328 - 0
lib/adc/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 */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 7903 - 0
lib/adc/stm32wbxx_hal_tim.c

@@ -0,0 +1,7903 @@
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_tim.c
+  * @author  MCD Application Team
+  * @brief   TIM HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the Timer (TIM) peripheral:
+  *           + TIM Time Base Initialization
+  *           + TIM Time Base Start
+  *           + TIM Time Base Start Interruption
+  *           + TIM Time Base Start DMA
+  *           + TIM Output Compare/PWM Initialization
+  *           + TIM Output Compare/PWM Channel Configuration
+  *           + TIM Output Compare/PWM  Start
+  *           + TIM Output Compare/PWM  Start Interruption
+  *           + TIM Output Compare/PWM Start DMA
+  *           + TIM Input Capture Initialization
+  *           + TIM Input Capture Channel Configuration
+  *           + TIM Input Capture Start
+  *           + TIM Input Capture Start Interruption
+  *           + TIM Input Capture Start DMA
+  *           + TIM One Pulse Initialization
+  *           + TIM One Pulse Channel Configuration
+  *           + TIM One Pulse Start
+  *           + TIM Encoder Interface Initialization
+  *           + TIM Encoder Interface Start
+  *           + TIM Encoder Interface Start Interruption
+  *           + TIM Encoder Interface Start DMA
+  *           + Commutation Event configuration with Interruption and DMA
+  *           + TIM OCRef clear configuration
+  *           + TIM External Clock configuration
+  ******************************************************************************
+  * @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
+  ==============================================================================
+                      ##### TIMER Generic features #####
+  ==============================================================================
+  [..] The Timer features include:
+       (#) 16-bit up, down, up/down auto-reload counter.
+       (#) 16-bit programmable prescaler allowing dividing (also on the fly) the
+           counter clock frequency either by any factor between 1 and 65536.
+       (#) Up to 4 independent channels for:
+           (++) Input Capture
+           (++) Output Compare
+           (++) PWM generation (Edge and Center-aligned Mode)
+           (++) One-pulse mode output
+       (#) Synchronization circuit to control the timer with external signals and to interconnect
+            several timers together.
+       (#) Supports incremental encoder for positioning purposes
+
+            ##### How to use this driver #####
+  ==============================================================================
+    [..]
+     (#) Initialize the TIM low level resources by implementing the following functions
+         depending on the selected feature:
+           (++) Time Base : HAL_TIM_Base_MspInit()
+           (++) Input Capture : HAL_TIM_IC_MspInit()
+           (++) Output Compare : HAL_TIM_OC_MspInit()
+           (++) PWM generation : HAL_TIM_PWM_MspInit()
+           (++) One-pulse mode output : HAL_TIM_OnePulse_MspInit()
+           (++) Encoder mode output : HAL_TIM_Encoder_MspInit()
+
+     (#) Initialize the TIM low level resources :
+        (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
+        (##) TIM pins configuration
+            (+++) Enable the clock for the TIM GPIOs using the following function:
+             __HAL_RCC_GPIOx_CLK_ENABLE();
+            (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
+
+     (#) The external Clock can be configured, if needed (the default clock is the
+         internal clock from the APBx), using the following function:
+         HAL_TIM_ConfigClockSource, the clock configuration should be done before
+         any start function.
+
+     (#) Configure the TIM in the desired functioning mode using one of the
+       Initialization function of this driver:
+       (++) HAL_TIM_Base_Init: to use the Timer to generate a simple time base
+       (++) HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer to generate an
+            Output Compare signal.
+       (++) HAL_TIM_PWM_Init and HAL_TIM_PWM_ConfigChannel: to use the Timer to generate a
+            PWM signal.
+       (++) HAL_TIM_IC_Init and HAL_TIM_IC_ConfigChannel: to use the Timer to measure an
+            external signal.
+       (++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer
+            in One Pulse Mode.
+       (++) HAL_TIM_Encoder_Init: to use the Timer Encoder Interface.
+
+     (#) Activate the TIM peripheral using one of the start functions depending from the feature used:
+           (++) Time Base : HAL_TIM_Base_Start(), HAL_TIM_Base_Start_DMA(), HAL_TIM_Base_Start_IT()
+           (++) Input Capture :  HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(), HAL_TIM_IC_Start_IT()
+           (++) Output Compare : HAL_TIM_OC_Start(), HAL_TIM_OC_Start_DMA(), HAL_TIM_OC_Start_IT()
+           (++) PWM generation : HAL_TIM_PWM_Start(), HAL_TIM_PWM_Start_DMA(), HAL_TIM_PWM_Start_IT()
+           (++) One-pulse mode output : HAL_TIM_OnePulse_Start(), HAL_TIM_OnePulse_Start_IT()
+           (++) Encoder mode output : HAL_TIM_Encoder_Start(), HAL_TIM_Encoder_Start_DMA(), HAL_TIM_Encoder_Start_IT().
+
+     (#) The DMA Burst is managed with the two following functions:
+         HAL_TIM_DMABurst_WriteStart()
+         HAL_TIM_DMABurst_ReadStart()
+
+    *** Callback registration ***
+  =============================================
+
+  [..]
+  The compilation define  USE_HAL_TIM_REGISTER_CALLBACKS when set to 1
+  allows the user to configure dynamically the driver callbacks.
+
+  [..]
+  Use Function HAL_TIM_RegisterCallback() to register a callback.
+  HAL_TIM_RegisterCallback() takes as parameters the HAL peripheral handle,
+  the Callback ID and a pointer to the user callback function.
+
+  [..]
+  Use function HAL_TIM_UnRegisterCallback() to reset a callback to the default
+  weak function.
+  HAL_TIM_UnRegisterCallback takes as parameters the HAL peripheral handle,
+  and the Callback ID.
+
+  [..]
+  These functions allow to register/unregister following callbacks:
+    (+) Base_MspInitCallback              : TIM Base Msp Init Callback.
+    (+) Base_MspDeInitCallback            : TIM Base Msp DeInit Callback.
+    (+) IC_MspInitCallback                : TIM IC Msp Init Callback.
+    (+) IC_MspDeInitCallback              : TIM IC Msp DeInit Callback.
+    (+) OC_MspInitCallback                : TIM OC Msp Init Callback.
+    (+) OC_MspDeInitCallback              : TIM OC Msp DeInit Callback.
+    (+) PWM_MspInitCallback               : TIM PWM Msp Init Callback.
+    (+) PWM_MspDeInitCallback             : TIM PWM Msp DeInit Callback.
+    (+) OnePulse_MspInitCallback          : TIM One Pulse Msp Init Callback.
+    (+) OnePulse_MspDeInitCallback        : TIM One Pulse Msp DeInit Callback.
+    (+) Encoder_MspInitCallback           : TIM Encoder Msp Init Callback.
+    (+) Encoder_MspDeInitCallback         : TIM Encoder Msp DeInit Callback.
+    (+) HallSensor_MspInitCallback        : TIM Hall Sensor Msp Init Callback.
+    (+) HallSensor_MspDeInitCallback      : TIM Hall Sensor Msp DeInit Callback.
+    (+) PeriodElapsedCallback             : TIM Period Elapsed Callback.
+    (+) PeriodElapsedHalfCpltCallback     : TIM Period Elapsed half complete Callback.
+    (+) TriggerCallback                   : TIM Trigger Callback.
+    (+) TriggerHalfCpltCallback           : TIM Trigger half complete Callback.
+    (+) IC_CaptureCallback                : TIM Input Capture Callback.
+    (+) IC_CaptureHalfCpltCallback        : TIM Input Capture half complete Callback.
+    (+) OC_DelayElapsedCallback           : TIM Output Compare Delay Elapsed Callback.
+    (+) PWM_PulseFinishedCallback         : TIM PWM Pulse Finished Callback.
+    (+) PWM_PulseFinishedHalfCpltCallback : TIM PWM Pulse Finished half complete Callback.
+    (+) ErrorCallback                     : TIM Error Callback.
+    (+) CommutationCallback               : TIM Commutation Callback.
+    (+) CommutationHalfCpltCallback       : TIM Commutation half complete Callback.
+    (+) BreakCallback                     : TIM Break Callback.
+    (+) Break2Callback                    : TIM Break2 Callback.
+
+  [..]
+By default, after the Init and when the state is HAL_TIM_STATE_RESET
+all interrupt callbacks are set to the corresponding weak functions:
+  examples HAL_TIM_TriggerCallback(), HAL_TIM_ErrorCallback().
+
+  [..]
+  Exception done for MspInit and MspDeInit functions that are reset to the legacy weak
+  functionalities in the Init / DeInit only when these callbacks are null
+  (not registered beforehand). If not, MspInit or MspDeInit are not null, the Init / DeInit
+    keep and use the user MspInit / MspDeInit callbacks(registered beforehand)
+
+  [..]
+    Callbacks can be registered / unregistered in HAL_TIM_STATE_READY state only.
+    Exception done MspInit / MspDeInit that can be registered / unregistered
+    in HAL_TIM_STATE_READY or HAL_TIM_STATE_RESET state,
+    thus registered(user) MspInit / DeInit callbacks can be used during the Init / DeInit.
+  In that case first register the MspInit/MspDeInit user callbacks
+      using HAL_TIM_RegisterCallback() before calling DeInit or Init function.
+
+  [..]
+      When The compilation define USE_HAL_TIM_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.
+
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup TIM TIM
+  * @brief TIM HAL module driver
+  * @{
+  */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup TIM_Private_Constants
+  * @{
+  */
+#define TIMx_AF1_ETRSEL TIM1_AF1_ETRSEL
+/**
+  * @}
+  */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup TIM_Private_Functions
+  * @{
+  */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter);
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter);
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter);
+static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint32_t InputTriggerSource);
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMAPeriodElapsedHalfCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+                                                  const TIM_SlaveConfigTypeDef *sSlaveConfig);
+/**
+  * @}
+  */
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup TIM_Exported_Functions TIM Exported Functions
+  * @{
+  */
+
+/** @defgroup TIM_Exported_Functions_Group1 TIM Time Base functions
+  *  @brief    Time Base functions
+  *
+@verbatim
+  ==============================================================================
+              ##### Time Base functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM base.
+    (+) De-initialize the TIM base.
+    (+) Start the Time Base.
+    (+) Stop the Time Base.
+    (+) Start the Time Base and enable interrupt.
+    (+) Stop the Time Base and disable interrupt.
+    (+) Start the Time Base and enable DMA transfer.
+    (+) Stop the Time Base and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Time base Unit according to the specified
+  *         parameters in the TIM_HandleTypeDef and initialize the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_Base_DeInit() before HAL_TIM_Base_Init()
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->Base_MspInitCallback == NULL)
+    {
+      htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->Base_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    HAL_TIM_Base_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Set the Time Base configuration */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM Base peripheral
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->Base_MspDeInitCallback == NULL)
+  {
+    htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->Base_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIM_Base_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Base MSP.
+  * @param  htim TIM Base handle
+  * @retval None
+  */
+__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Base_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Base MSP.
+  * @param  htim TIM Base handle
+  * @retval None
+  */
+__weak void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Base_MspDeInit could be implemented in the user file
+   */
+}
+
+
+/**
+  * @brief  Starts the TIM Base generation.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Check the TIM state */
+  if (htim->State != HAL_TIM_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Base generation.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Base generation in interrupt mode.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Check the TIM state */
+  if (htim->State != HAL_TIM_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Enable the TIM Update interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Base generation in interrupt mode.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  /* Disable the TIM Update interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Base generation in DMA mode.
+  * @param  htim TIM Base handle
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+  /* Set the TIM state */
+  if (htim->State == HAL_TIM_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (htim->State == HAL_TIM_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      htim->State = HAL_TIM_STATE_BUSY;
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the DMA Period elapsed callbacks */
+  htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+  htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+  /* Set the DMA error callback */
+  htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+  /* Enable the DMA channel */
+  if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&htim->Instance->ARR,
+                       Length) != HAL_OK)
+  {
+    /* Return error status */
+    return HAL_ERROR;
+  }
+
+  /* Enable the TIM Update DMA request */
+  __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Base generation in DMA mode.
+  * @param  htim TIM Base handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+  /* Disable the TIM Update DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_UPDATE);
+
+  (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group2 TIM Output Compare functions
+  *  @brief    TIM Output Compare functions
+  *
+@verbatim
+  ==============================================================================
+                  ##### TIM Output Compare functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM Output Compare.
+    (+) De-initialize the TIM Output Compare.
+    (+) Start the TIM Output Compare.
+    (+) Stop the TIM Output Compare.
+    (+) Start the TIM Output Compare and enable interrupt.
+    (+) Stop the TIM Output Compare and disable interrupt.
+    (+) Start the TIM Output Compare and enable DMA transfer.
+    (+) Stop the TIM Output Compare and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Output Compare according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_OC_DeInit() before HAL_TIM_OC_Init()
+  * @param  htim TIM Output Compare handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->OC_MspInitCallback == NULL)
+    {
+      htim->OC_MspInitCallback = HAL_TIM_OC_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->OC_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_OC_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Init the base time for the Output Compare */
+  TIM_Base_SetConfig(htim->Instance,  &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM peripheral
+  * @param  htim TIM Output Compare handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->OC_MspDeInitCallback == NULL)
+  {
+    htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->OC_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+  HAL_TIM_OC_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Output Compare MSP.
+  * @param  htim TIM Output Compare handle
+  * @retval None
+  */
+__weak void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OC_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Output Compare MSP.
+  * @param  htim TIM Output Compare handle
+  * @retval None
+  */
+__weak void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OC_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Output compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Output compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in interrupt mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Enable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in interrupt mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in DMA mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                       uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 4 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in DMA mode.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Output compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group3 TIM PWM functions
+  *  @brief    TIM PWM functions
+  *
+@verbatim
+  ==============================================================================
+                          ##### TIM PWM functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM PWM.
+    (+) De-initialize the TIM PWM.
+    (+) Start the TIM PWM.
+    (+) Stop the TIM PWM.
+    (+) Start the TIM PWM and enable interrupt.
+    (+) Stop the TIM PWM and disable interrupt.
+    (+) Start the TIM PWM and enable DMA transfer.
+    (+) Stop the TIM PWM and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM PWM Time Base according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_PWM_DeInit() before HAL_TIM_PWM_Init()
+  * @param  htim TIM PWM handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->PWM_MspInitCallback == NULL)
+    {
+      htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->PWM_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_PWM_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Init the base time for the PWM */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM peripheral
+  * @param  htim TIM PWM handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->PWM_MspDeInitCallback == NULL)
+  {
+    htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->PWM_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+  HAL_TIM_PWM_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM PWM MSP.
+  * @param  htim TIM PWM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM PWM MSP.
+  * @param  htim TIM PWM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the PWM signal generation.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the PWM signal generation.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Capture compare channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the PWM signal generation in interrupt mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Enable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the PWM signal generation in interrupt mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM PWM signal generation in DMA mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                        uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM channel state */
+  if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Capture/Compare 3 request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 4 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Enable the main output */
+      __HAL_TIM_MOE_ENABLE(htim);
+    }
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM PWM signal generation in DMA mode.
+  * @param  htim TIM PWM handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+    {
+      /* Disable the Main Output */
+      __HAL_TIM_MOE_DISABLE(htim);
+    }
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group4 TIM Input Capture functions
+  *  @brief    TIM Input Capture functions
+  *
+@verbatim
+  ==============================================================================
+              ##### TIM Input Capture functions #####
+  ==============================================================================
+ [..]
+   This section provides functions allowing to:
+   (+) Initialize and configure the TIM Input Capture.
+   (+) De-initialize the TIM Input Capture.
+   (+) Start the TIM Input Capture.
+   (+) Stop the TIM Input Capture.
+   (+) Start the TIM Input Capture and enable interrupt.
+   (+) Stop the TIM Input Capture and disable interrupt.
+   (+) Start the TIM Input Capture and enable DMA transfer.
+   (+) Stop the TIM Input Capture and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Input Capture Time base according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_IC_DeInit() before HAL_TIM_IC_Init()
+  * @param  htim TIM Input Capture handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->IC_MspInitCallback == NULL)
+    {
+      htim->IC_MspInitCallback = HAL_TIM_IC_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->IC_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_IC_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Init the base time for the input capture */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM peripheral
+  * @param  htim TIM Input Capture handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->IC_MspDeInitCallback == NULL)
+  {
+    htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->IC_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+  HAL_TIM_IC_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Input Capture MSP.
+  * @param  htim TIM Input Capture handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Input Capture MSP.
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Input Capture measurement.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if ((channel_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Input Capture measurement.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Input Capture measurement in interrupt mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM channel state */
+  if ((channel_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Enable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Input Capture channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Input Capture measurement in interrupt mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Input Capture channel */
+    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM Input Capture measurement in DMA mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @param  pData The destination Buffer address.
+  * @param  Length The length of data to be transferred from TIM peripheral to memory.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+  assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel state */
+  if ((channel_state == HAL_TIM_CHANNEL_STATE_BUSY)
+      || (complementary_channel_state == HAL_TIM_CHANNEL_STATE_BUSY))
+  {
+    return HAL_BUSY;
+  }
+  else if ((channel_state == HAL_TIM_CHANNEL_STATE_READY)
+           && (complementary_channel_state == HAL_TIM_CHANNEL_STATE_READY))
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  /* Enable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 2  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->CCR3, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 3  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->CCR4, (uint32_t)pData,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 4  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Input Capture measurement in DMA mode.
+  * @param  htim TIM Input Capture handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+  assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channel */
+  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3  DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Disable the TIM Capture/Compare 4  DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM channel state */
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group5 TIM One Pulse functions
+  *  @brief    TIM One Pulse functions
+  *
+@verbatim
+  ==============================================================================
+                        ##### TIM One Pulse functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM One Pulse.
+    (+) De-initialize the TIM One Pulse.
+    (+) Start the TIM One Pulse.
+    (+) Stop the TIM One Pulse.
+    (+) Start the TIM One Pulse and enable interrupt.
+    (+) Stop the TIM One Pulse and disable interrupt.
+    (+) Start the TIM One Pulse and enable DMA transfer.
+    (+) Stop the TIM One Pulse and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM One Pulse Time Base according to the specified
+  *         parameters in the TIM_HandleTypeDef and initializes the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_OnePulse_DeInit() before HAL_TIM_OnePulse_Init()
+  * @note   When the timer instance is initialized in One Pulse mode, timer
+  *         channels 1 and channel 2 are reserved and cannot be used for other
+  *         purpose.
+  * @param  htim TIM One Pulse handle
+  * @param  OnePulseMode Select the One pulse mode.
+  *         This parameter can be one of the following values:
+  *            @arg TIM_OPMODE_SINGLE: Only one pulse will be generated.
+  *            @arg TIM_OPMODE_REPETITIVE: Repetitive pulses will be generated.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode)
+{
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_OPM_MODE(OnePulseMode));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->OnePulse_MspInitCallback == NULL)
+    {
+      htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->OnePulse_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_OnePulse_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Configure the Time base in the One Pulse Mode */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Reset the OPM Bit */
+  htim->Instance->CR1 &= ~TIM_CR1_OPM;
+
+  /* Configure the OPM Mode */
+  htim->Instance->CR1 |= OnePulseMode;
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM One Pulse
+  * @param  htim TIM One Pulse handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->OnePulse_MspDeInitCallback == NULL)
+  {
+    htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->OnePulse_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIM_OnePulse_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM One Pulse MSP.
+  * @param  htim TIM One Pulse handle
+  * @retval None
+  */
+__weak void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OnePulse_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM One Pulse MSP.
+  * @param  htim TIM One Pulse handle
+  * @retval None
+  */
+__weak void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OnePulse_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare and the Input Capture channels
+    (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+    if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+    if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+    whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+    No need to enable the counter, it's enabled automatically by hardware
+    (the counter starts in response to a stimulus and generate a pulse */
+
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Disable the Capture compare and the Input Capture channels
+  (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+  if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+  if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+  whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation in interrupt mode.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare and the Input Capture channels
+    (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+    if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+    if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+    whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+    No need to enable the counter, it's enabled automatically by hardware
+    (the counter starts in response to a stimulus and generate a pulse */
+
+  /* Enable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+  /* Enable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Enable the main output */
+    __HAL_TIM_MOE_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation in interrupt mode.
+  * @note Though OutputChannel parameter is deprecated and ignored by the function
+  *        it has been kept to avoid HAL_TIM API compatibility break.
+  * @note The pulse output channel is determined when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel See note above
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(OutputChannel);
+
+  /* Disable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+  /* Disable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+  /* Disable the Capture compare and the Input Capture channels
+  (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+  if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+  if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+  whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+  if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+  {
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group6 TIM Encoder functions
+  *  @brief    TIM Encoder functions
+  *
+@verbatim
+  ==============================================================================
+                          ##### TIM Encoder functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure the TIM Encoder.
+    (+) De-initialize the TIM Encoder.
+    (+) Start the TIM Encoder.
+    (+) Stop the TIM Encoder.
+    (+) Start the TIM Encoder and enable interrupt.
+    (+) Stop the TIM Encoder and disable interrupt.
+    (+) Start the TIM Encoder and enable DMA transfer.
+    (+) Stop the TIM Encoder and disable DMA transfer.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Encoder Interface and initialize the associated handle.
+  * @note   Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+  *         requires a timer reset to avoid unexpected direction
+  *         due to DIR bit readonly in center aligned mode.
+  *         Ex: call @ref HAL_TIM_Encoder_DeInit() before HAL_TIM_Encoder_Init()
+  * @note   Encoder mode and External clock mode 2 are not compatible and must not be selected together
+  *         Ex: A call for @ref HAL_TIM_Encoder_Init will erase the settings of @ref HAL_TIM_ConfigClockSource
+  *         using TIM_CLOCKSOURCE_ETRMODE2 and vice versa
+  * @note   When the timer instance is initialized in Encoder mode, timer
+  *         channels 1 and channel 2 are reserved and cannot be used for other
+  *         purpose.
+  * @param  htim TIM Encoder Interface handle
+  * @param  sConfig TIM Encoder Interface configuration structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim,  TIM_Encoder_InitTypeDef *sConfig)
+{
+  uint32_t tmpsmcr;
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+  assert_param(IS_TIM_ENCODER_MODE(sConfig->EncoderMode));
+  assert_param(IS_TIM_IC_SELECTION(sConfig->IC1Selection));
+  assert_param(IS_TIM_IC_SELECTION(sConfig->IC2Selection));
+  assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC1Polarity));
+  assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC2Polarity));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->IC2Prescaler));
+  assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+  assert_param(IS_TIM_IC_FILTER(sConfig->IC2Filter));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy weak callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->Encoder_MspInitCallback == NULL)
+    {
+      htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->Encoder_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIM_Encoder_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Reset the SMS and ECE bits */
+  htim->Instance->SMCR &= ~(TIM_SMCR_SMS | TIM_SMCR_ECE);
+
+  /* Configure the Time base in the Encoder Mode */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = htim->Instance->SMCR;
+
+  /* Get the TIMx CCMR1 register value */
+  tmpccmr1 = htim->Instance->CCMR1;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = htim->Instance->CCER;
+
+  /* Set the encoder Mode */
+  tmpsmcr |= sConfig->EncoderMode;
+
+  /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+  tmpccmr1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S);
+  tmpccmr1 |= (sConfig->IC1Selection | (sConfig->IC2Selection << 8U));
+
+  /* Set the Capture Compare 1 and the Capture Compare 2 prescalers and filters */
+  tmpccmr1 &= ~(TIM_CCMR1_IC1PSC | TIM_CCMR1_IC2PSC);
+  tmpccmr1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_IC2F);
+  tmpccmr1 |= sConfig->IC1Prescaler | (sConfig->IC2Prescaler << 8U);
+  tmpccmr1 |= (sConfig->IC1Filter << 4U) | (sConfig->IC2Filter << 12U);
+
+  /* Set the TI1 and the TI2 Polarities */
+  tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC2P);
+  tmpccer &= ~(TIM_CCER_CC1NP | TIM_CCER_CC2NP);
+  tmpccer |= sConfig->IC1Polarity | (sConfig->IC2Polarity << 4U);
+
+  /* Write to TIMx SMCR */
+  htim->Instance->SMCR = tmpsmcr;
+
+  /* Write to TIMx CCMR1 */
+  htim->Instance->CCMR1 = tmpccmr1;
+
+  /* Write to TIMx CCER */
+  htim->Instance->CCER = tmpccer;
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+
+/**
+  * @brief  DeInitializes the TIM Encoder interface
+  * @param  htim TIM Encoder Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->Encoder_MspDeInitCallback == NULL)
+  {
+    htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->Encoder_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIM_Encoder_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Encoder Interface MSP.
+  * @param  htim TIM Encoder Interface handle
+  * @retval None
+  */
+__weak void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Encoder_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Encoder Interface MSP.
+  * @param  htim TIM Encoder Interface handle
+  * @retval None
+  */
+__weak void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_Encoder_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Encoder Interface.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel(s) state */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    if ((channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+
+  /* Enable the encoder interface channels */
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      break;
+    }
+
+    default :
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      break;
+    }
+  }
+  /* Enable the Peripheral */
+  __HAL_TIM_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Encoder Interface.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1 and 2
+    (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+      break;
+    }
+
+    default :
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+      break;
+    }
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel(s) state */
+  if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+  {
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Encoder Interface in interrupt mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel(s) state */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    if ((channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+        || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+
+  /* Enable the encoder interface channels */
+  /* Enable the capture compare Interrupts 1 and/or 2 */
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    default :
+    {
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+  }
+
+  /* Enable the Peripheral */
+  __HAL_TIM_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Encoder Interface in interrupt mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1 and 2
+    (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare Interrupts 1 */
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare Interrupts 2 */
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+  }
+  else
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare Interrupts 1 and 2 */
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+    __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel(s) state */
+  if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+  {
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Encoder Interface in DMA mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @param  pData1 The destination Buffer address for IC1.
+  * @param  pData2 The destination Buffer address for IC2.
+  * @param  Length The length of data to be transferred from TIM peripheral to memory.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1,
+                                            uint32_t *pData2, uint16_t Length)
+{
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel(s) state */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
+    {
+      return HAL_BUSY;
+    }
+    else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
+    {
+      if ((pData1 == NULL) || (Length == 0U))
+      {
+        return HAL_ERROR;
+      }
+      else
+      {
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      }
+    }
+    else
+    {
+      return HAL_ERROR;
+    }
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    if ((channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY))
+    {
+      return HAL_BUSY;
+    }
+    else if ((channel_2_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_READY))
+    {
+      if ((pData2 == NULL) || (Length == 0U))
+      {
+        return HAL_ERROR;
+      }
+      else
+      {
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      }
+    }
+    else
+    {
+      return HAL_ERROR;
+    }
+  }
+  else
+  {
+    if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+        || (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY))
+    {
+      return HAL_BUSY;
+    }
+    else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (channel_2_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+             && (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_READY))
+    {
+      if ((((pData1 == NULL) || (pData2 == NULL))) || (Length == 0U))
+      {
+        return HAL_ERROR;
+      }
+      else
+      {
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+        TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+      }
+    }
+    else
+    {
+      return HAL_ERROR;
+    }
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Input Capture DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+      /* Enable the Capture compare channel */
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+      /* Enable the Peripheral */
+      __HAL_TIM_ENABLE(htim);
+
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError;
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Input Capture  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+      /* Enable the Capture compare channel */
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+      /* Enable the Peripheral */
+      __HAL_TIM_ENABLE(htim);
+
+      break;
+    }
+
+    default:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+
+      /* Enable the TIM Input Capture  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      /* Enable the TIM Input Capture  DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+      /* Enable the Capture compare channel */
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+      TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+      /* Enable the Peripheral */
+      __HAL_TIM_ENABLE(htim);
+
+      break;
+    }
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Encoder Interface in DMA mode.
+  * @param  htim TIM Encoder Interface handle
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1 and 2
+    (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+  if (Channel == TIM_CHANNEL_1)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare DMA Request 1 */
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare DMA Request 2 */
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+  }
+  else
+  {
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+    TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+    /* Disable the capture compare DMA Request 1 and 2 */
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+    __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+    (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+  }
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel(s) state */
+  if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+  {
+    TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+  *  @brief    TIM IRQ handler management
+  *
+@verbatim
+  ==============================================================================
+                        ##### IRQ handler management #####
+  ==============================================================================
+  [..]
+    This section provides Timer IRQ handler function.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  This function handles TIM interrupts requests.
+  * @param  htim TIM  handle
+  * @retval None
+  */
+void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
+{
+  /* Capture compare 1 event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET)
+    {
+      {
+        __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
+        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+        /* Input capture event */
+        if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
+        {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+          htim->IC_CaptureCallback(htim);
+#else
+          HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+        }
+        /* Output compare event */
+        else
+        {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+          htim->OC_DelayElapsedCallback(htim);
+          htim->PWM_PulseFinishedCallback(htim);
+#else
+          HAL_TIM_OC_DelayElapsedCallback(htim);
+          HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+        }
+        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+      }
+    }
+  }
+  /* Capture compare 2 event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+      /* Input capture event */
+      if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->IC_CaptureCallback(htim);
+#else
+        HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      /* Output compare event */
+      else
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->OC_DelayElapsedCallback(htim);
+        htim->PWM_PulseFinishedCallback(htim);
+#else
+        HAL_TIM_OC_DelayElapsedCallback(htim);
+        HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+    }
+  }
+  /* Capture compare 3 event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+      /* Input capture event */
+      if ((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->IC_CaptureCallback(htim);
+#else
+        HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      /* Output compare event */
+      else
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->OC_DelayElapsedCallback(htim);
+        htim->PWM_PulseFinishedCallback(htim);
+#else
+        HAL_TIM_OC_DelayElapsedCallback(htim);
+        HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+    }
+  }
+  /* Capture compare 4 event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+      /* Input capture event */
+      if ((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->IC_CaptureCallback(htim);
+#else
+        HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      /* Output compare event */
+      else
+      {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+        htim->OC_DelayElapsedCallback(htim);
+        htim->PWM_PulseFinishedCallback(htim);
+#else
+        HAL_TIM_OC_DelayElapsedCallback(htim);
+        HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+      }
+      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+    }
+  }
+  /* TIM Update event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->PeriodElapsedCallback(htim);
+#else
+      HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM Break input event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->BreakCallback(htim);
+#else
+      HAL_TIMEx_BreakCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM Break2 input event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK2) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) != RESET)
+    {
+      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_BREAK2);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->Break2Callback(htim);
+#else
+      HAL_TIMEx_Break2Callback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM Trigger detection event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->TriggerCallback(htim);
+#else
+      HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+  /* TIM commutation event */
+  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
+  {
+    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) != RESET)
+    {
+      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+      htim->CommutationCallback(htim);
+#else
+      HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+    }
+  }
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group8 TIM Peripheral Control functions
+  *  @brief    TIM Peripheral Control functions
+  *
+@verbatim
+  ==============================================================================
+                   ##### Peripheral Control functions #####
+  ==============================================================================
+ [..]
+   This section provides functions allowing to:
+      (+) Configure The Input Output channels for OC, PWM, IC or One Pulse mode.
+      (+) Configure External Clock source.
+      (+) Configure Complementary channels, break features and dead time.
+      (+) Configure Master and the Slave synchronization.
+      (+) Configure the DMA Burst Mode.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initializes the TIM Output Compare Channels according to the specified
+  *         parameters in the TIM_OC_InitTypeDef.
+  * @param  htim TIM Output Compare handle
+  * @param  sConfig TIM Output Compare configuration structure
+  * @param  Channel TIM Channels to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim,
+                                           const TIM_OC_InitTypeDef *sConfig,
+                                           uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CHANNELS(Channel));
+  assert_param(IS_TIM_OC_MODE(sConfig->OCMode));
+  assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 1 in Output Compare */
+      TIM_OC1_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 2 in Output Compare */
+      TIM_OC2_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 3 in Output Compare */
+      TIM_OC3_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 4 in Output Compare */
+      TIM_OC4_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_5:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC5_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 5 in Output Compare */
+      TIM_OC5_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    case TIM_CHANNEL_6:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC6_INSTANCE(htim->Instance));
+
+      /* Configure the TIM Channel 6 in Output Compare */
+      TIM_OC6_SetConfig(htim->Instance, sConfig);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Initializes the TIM Input Capture Channels according to the specified
+  *         parameters in the TIM_IC_InitTypeDef.
+  * @param  htim TIM IC handle
+  * @param  sConfig TIM Input Capture configuration structure
+  * @param  Channel TIM Channel to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_IC_POLARITY(sConfig->ICPolarity));
+  assert_param(IS_TIM_IC_SELECTION(sConfig->ICSelection));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->ICPrescaler));
+  assert_param(IS_TIM_IC_FILTER(sConfig->ICFilter));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  if (Channel == TIM_CHANNEL_1)
+  {
+    /* TI1 Configuration */
+    TIM_TI1_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC1PSC Bits */
+    htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+    /* Set the IC1PSC value */
+    htim->Instance->CCMR1 |= sConfig->ICPrescaler;
+  }
+  else if (Channel == TIM_CHANNEL_2)
+  {
+    /* TI2 Configuration */
+    assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+    TIM_TI2_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC2PSC Bits */
+    htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+    /* Set the IC2PSC value */
+    htim->Instance->CCMR1 |= (sConfig->ICPrescaler << 8U);
+  }
+  else if (Channel == TIM_CHANNEL_3)
+  {
+    /* TI3 Configuration */
+    assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+    TIM_TI3_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC3PSC Bits */
+    htim->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC;
+
+    /* Set the IC3PSC value */
+    htim->Instance->CCMR2 |= sConfig->ICPrescaler;
+  }
+  else if (Channel == TIM_CHANNEL_4)
+  {
+    /* TI4 Configuration */
+    assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+    TIM_TI4_SetConfig(htim->Instance,
+                      sConfig->ICPolarity,
+                      sConfig->ICSelection,
+                      sConfig->ICFilter);
+
+    /* Reset the IC4PSC Bits */
+    htim->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC;
+
+    /* Set the IC4PSC value */
+    htim->Instance->CCMR2 |= (sConfig->ICPrescaler << 8U);
+  }
+  else
+  {
+    status = HAL_ERROR;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Initializes the TIM PWM  channels according to the specified
+  *         parameters in the TIM_OC_InitTypeDef.
+  * @param  htim TIM PWM handle
+  * @param  sConfig TIM PWM configuration structure
+  * @param  Channel TIM Channels to be configured
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
+                                            const TIM_OC_InitTypeDef *sConfig,
+                                            uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CHANNELS(Channel));
+  assert_param(IS_TIM_PWM_MODE(sConfig->OCMode));
+  assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+  assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 1 in PWM mode */
+      TIM_OC1_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel1 */
+      htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE;
+      htim->Instance->CCMR1 |= sConfig->OCFastMode;
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 2 in PWM mode */
+      TIM_OC2_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel2 */
+      htim->Instance->CCMR1 |= TIM_CCMR1_OC2PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE;
+      htim->Instance->CCMR1 |= sConfig->OCFastMode << 8U;
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 3 in PWM mode */
+      TIM_OC3_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel3 */
+      htim->Instance->CCMR2 |= TIM_CCMR2_OC3PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE;
+      htim->Instance->CCMR2 |= sConfig->OCFastMode;
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 4 in PWM mode */
+      TIM_OC4_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel4 */
+      htim->Instance->CCMR2 |= TIM_CCMR2_OC4PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE;
+      htim->Instance->CCMR2 |= sConfig->OCFastMode << 8U;
+      break;
+    }
+
+    case TIM_CHANNEL_5:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC5_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 5 in PWM mode */
+      TIM_OC5_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel5*/
+      htim->Instance->CCMR3 |= TIM_CCMR3_OC5PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5FE;
+      htim->Instance->CCMR3 |= sConfig->OCFastMode;
+      break;
+    }
+
+    case TIM_CHANNEL_6:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC6_INSTANCE(htim->Instance));
+
+      /* Configure the Channel 6 in PWM mode */
+      TIM_OC6_SetConfig(htim->Instance, sConfig);
+
+      /* Set the Preload enable bit for channel6 */
+      htim->Instance->CCMR3 |= TIM_CCMR3_OC6PE;
+
+      /* Configure the Output Fast mode */
+      htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6FE;
+      htim->Instance->CCMR3 |= sConfig->OCFastMode << 8U;
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Initializes the TIM One Pulse Channels according to the specified
+  *         parameters in the TIM_OnePulse_InitTypeDef.
+  * @param  htim TIM One Pulse handle
+  * @param  sConfig TIM One Pulse configuration structure
+  * @param  OutputChannel TIM output channel to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @param  InputChannel TIM input Channel to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @note  To output a waveform with a minimum delay user can enable the fast
+  *        mode by calling the @ref __HAL_TIM_ENABLE_OCxFAST macro. Then CCx
+  *        output is forced in response to the edge detection on TIx input,
+  *        without taking in account the comparison.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim,  TIM_OnePulse_InitTypeDef *sConfig,
+                                                 uint32_t OutputChannel,  uint32_t InputChannel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  TIM_OC_InitTypeDef temp1;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_OPM_CHANNELS(OutputChannel));
+  assert_param(IS_TIM_OPM_CHANNELS(InputChannel));
+
+  if (OutputChannel != InputChannel)
+  {
+    /* Process Locked */
+    __HAL_LOCK(htim);
+
+    htim->State = HAL_TIM_STATE_BUSY;
+
+    /* Extract the Output compare configuration from sConfig structure */
+    temp1.OCMode = sConfig->OCMode;
+    temp1.Pulse = sConfig->Pulse;
+    temp1.OCPolarity = sConfig->OCPolarity;
+    temp1.OCNPolarity = sConfig->OCNPolarity;
+    temp1.OCIdleState = sConfig->OCIdleState;
+    temp1.OCNIdleState = sConfig->OCNIdleState;
+
+    switch (OutputChannel)
+    {
+      case TIM_CHANNEL_1:
+      {
+        assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+        TIM_OC1_SetConfig(htim->Instance, &temp1);
+        break;
+      }
+
+      case TIM_CHANNEL_2:
+      {
+        assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+        TIM_OC2_SetConfig(htim->Instance, &temp1);
+        break;
+      }
+
+      default:
+        status = HAL_ERROR;
+        break;
+    }
+
+    if (status == HAL_OK)
+    {
+      switch (InputChannel)
+      {
+        case TIM_CHANNEL_1:
+        {
+          assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+          TIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity,
+                            sConfig->ICSelection, sConfig->ICFilter);
+
+          /* Reset the IC1PSC Bits */
+          htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+          /* Select the Trigger source */
+          htim->Instance->SMCR &= ~TIM_SMCR_TS;
+          htim->Instance->SMCR |= TIM_TS_TI1FP1;
+
+          /* Select the Slave Mode */
+          htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+          htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+          break;
+        }
+
+        case TIM_CHANNEL_2:
+        {
+          assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+          TIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity,
+                            sConfig->ICSelection, sConfig->ICFilter);
+
+          /* Reset the IC2PSC Bits */
+          htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+          /* Select the Trigger source */
+          htim->Instance->SMCR &= ~TIM_SMCR_TS;
+          htim->Instance->SMCR |= TIM_TS_TI2FP2;
+
+          /* Select the Slave Mode */
+          htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+          htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+          break;
+        }
+
+        default:
+          status = HAL_ERROR;
+          break;
+      }
+    }
+
+    htim->State = HAL_TIM_STATE_READY;
+
+    __HAL_UNLOCK(htim);
+
+    return status;
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer Data from the memory to the TIM peripheral
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA  will start the Data write
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  *            @arg TIM_DMABASE_OR
+  *            @arg TIM_DMABASE_CCMR3
+  *            @arg TIM_DMABASE_CCR5
+  *            @arg TIM_DMABASE_CCR6
+  *            @arg TIM_DMABASE_AF1
+  *            @arg TIM_DMABASE_AF2
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @note   This function should be used only when BurstLength is equal to DMA data transfer length.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                              uint32_t BurstRequestSrc, const uint32_t *BurstBuffer, uint32_t  BurstLength)
+{
+  HAL_StatusTypeDef status;
+
+  status = HAL_TIM_DMABurst_MultiWriteStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+                                            ((BurstLength) >> 8U) + 1U);
+
+
+
+  return status;
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer multiple Data from the memory to the TIM peripheral
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA will start the Data write
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  *            @arg TIM_DMABASE_OR
+  *            @arg TIM_DMABASE_CCMR3
+  *            @arg TIM_DMABASE_CCR5
+  *            @arg TIM_DMABASE_CCR6
+  *            @arg TIM_DMABASE_AF1
+  *            @arg TIM_DMABASE_AF2
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @param  DataLength Data length. This parameter can be one value
+  *         between 1 and 0xFFFF.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                   uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+                                                   uint32_t  BurstLength,  uint32_t  DataLength)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_DMA_BASE(BurstBaseAddress));
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+  assert_param(IS_TIM_DMA_LENGTH(BurstLength));
+  assert_param(IS_TIM_DMA_DATA_LENGTH(DataLength));
+
+  if (htim->DMABurstState == HAL_DMA_BURST_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (htim->DMABurstState == HAL_DMA_BURST_STATE_READY)
+  {
+    if ((BurstBuffer == NULL) && (BurstLength > 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      htim->DMABurstState = HAL_DMA_BURST_STATE_BUSY;
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      /* Set the DMA Period elapsed callbacks */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      /* Set the DMA commutation callbacks */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback =  TIMEx_DMACommutationCplt;
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback =  TIMEx_DMACommutationHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      /* Set the DMA trigger callbacks */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferHalfCpltCallback = TIM_DMATriggerHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)BurstBuffer,
+                           (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Configure the DMA Burst Mode */
+    htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+    /* Enable the TIM DMA Request */
+    __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM DMA Burst mode
+  * @param  htim TIM handle
+  * @param  BurstRequestSrc TIM DMA Request sources to disable
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+
+  /* Abort the DMA transfer (at least disable the DMA channel) */
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the TIM Update DMA request */
+    __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+    /* Change the DMA burst operation state */
+    htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer Data from the TIM peripheral to the memory
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA  will start the Data read
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  *            @arg TIM_DMABASE_OR
+  *            @arg TIM_DMABASE_CCMR3
+  *            @arg TIM_DMABASE_CCR5
+  *            @arg TIM_DMABASE_CCR6
+  *            @arg TIM_DMABASE_AF1
+  *            @arg TIM_DMABASE_AF2
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @note   This function should be used only when BurstLength is equal to DMA data transfer length.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                             uint32_t BurstRequestSrc, uint32_t  *BurstBuffer, uint32_t  BurstLength)
+{
+  HAL_StatusTypeDef status;
+
+  status = HAL_TIM_DMABurst_MultiReadStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+                                           ((BurstLength) >> 8U) + 1U);
+
+
+  return status;
+}
+
+/**
+  * @brief  Configure the DMA Burst to transfer Data from the TIM peripheral to the memory
+  * @param  htim TIM handle
+  * @param  BurstBaseAddress TIM Base address from where the DMA  will start the Data read
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMABASE_CR1
+  *            @arg TIM_DMABASE_CR2
+  *            @arg TIM_DMABASE_SMCR
+  *            @arg TIM_DMABASE_DIER
+  *            @arg TIM_DMABASE_SR
+  *            @arg TIM_DMABASE_EGR
+  *            @arg TIM_DMABASE_CCMR1
+  *            @arg TIM_DMABASE_CCMR2
+  *            @arg TIM_DMABASE_CCER
+  *            @arg TIM_DMABASE_CNT
+  *            @arg TIM_DMABASE_PSC
+  *            @arg TIM_DMABASE_ARR
+  *            @arg TIM_DMABASE_RCR
+  *            @arg TIM_DMABASE_CCR1
+  *            @arg TIM_DMABASE_CCR2
+  *            @arg TIM_DMABASE_CCR3
+  *            @arg TIM_DMABASE_CCR4
+  *            @arg TIM_DMABASE_BDTR
+  *            @arg TIM_DMABASE_OR
+  *            @arg TIM_DMABASE_CCMR3
+  *            @arg TIM_DMABASE_CCR5
+  *            @arg TIM_DMABASE_CCR6
+  *            @arg TIM_DMABASE_AF1
+  *            @arg TIM_DMABASE_AF2
+  * @param  BurstRequestSrc TIM DMA Request sources
+  *         This parameter can be one of the following values:
+  *            @arg TIM_DMA_UPDATE: TIM update Interrupt source
+  *            @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+  *            @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+  *            @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+  *            @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+  *            @arg TIM_DMA_COM: TIM Commutation DMA source
+  *            @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+  * @param  BurstBuffer The Buffer address.
+  * @param  BurstLength DMA Burst length. This parameter can be one value
+  *         between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+  * @param  DataLength Data length. This parameter can be one value
+  *         between 1 and 0xFFFF.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+                                                  uint32_t BurstRequestSrc, uint32_t  *BurstBuffer,
+                                                  uint32_t  BurstLength, uint32_t  DataLength)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_DMA_BASE(BurstBaseAddress));
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+  assert_param(IS_TIM_DMA_LENGTH(BurstLength));
+  assert_param(IS_TIM_DMA_DATA_LENGTH(DataLength));
+
+  if (htim->DMABurstState == HAL_DMA_BURST_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (htim->DMABurstState == HAL_DMA_BURST_STATE_READY)
+  {
+    if ((BurstBuffer == NULL) && (BurstLength > 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      htim->DMABurstState = HAL_DMA_BURST_STATE_BUSY;
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      /* Set the DMA Period elapsed callbacks */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      /* Set the DMA capture callbacks */
+      htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+      htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      /* Set the DMA commutation callbacks */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback =  TIMEx_DMACommutationCplt;
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback =  TIMEx_DMACommutationHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      /* Set the DMA trigger callbacks */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferHalfCpltCallback = TIM_DMATriggerHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+                           DataLength) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Configure the DMA Burst Mode */
+    htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+
+    /* Enable the TIM DMA Request */
+    __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stop the DMA burst reading
+  * @param  htim TIM handle
+  * @param  BurstRequestSrc TIM DMA Request sources to disable.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+
+  /* Abort the DMA transfer (at least disable the DMA channel) */
+  switch (BurstRequestSrc)
+  {
+    case TIM_DMA_UPDATE:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+      break;
+    }
+    case TIM_DMA_CC1:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+    case TIM_DMA_CC2:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+    case TIM_DMA_CC3:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+    case TIM_DMA_CC4:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+      break;
+    }
+    case TIM_DMA_COM:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+      break;
+    }
+    case TIM_DMA_TRIGGER:
+    {
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the TIM Update DMA request */
+    __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+    /* Change the DMA burst operation state */
+    htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Generate a software event
+  * @param  htim TIM handle
+  * @param  EventSource specifies the event source.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_EVENTSOURCE_UPDATE: Timer update Event source
+  *            @arg TIM_EVENTSOURCE_CC1: Timer Capture Compare 1 Event source
+  *            @arg TIM_EVENTSOURCE_CC2: Timer Capture Compare 2 Event source
+  *            @arg TIM_EVENTSOURCE_CC3: Timer Capture Compare 3 Event source
+  *            @arg TIM_EVENTSOURCE_CC4: Timer Capture Compare 4 Event source
+  *            @arg TIM_EVENTSOURCE_COM: Timer COM event source
+  *            @arg TIM_EVENTSOURCE_TRIGGER: Timer Trigger Event source
+  *            @arg TIM_EVENTSOURCE_BREAK: Timer Break event source
+  *            @arg TIM_EVENTSOURCE_BREAK2: Timer Break2 event source
+  * @note   Basic timers can only generate an update event.
+  * @note   TIM_EVENTSOURCE_COM is relevant only with advanced timer instances.
+  * @note   TIM_EVENTSOURCE_BREAK and TIM_EVENTSOURCE_BREAK2 are relevant
+  *         only for timer instances supporting break input(s).
+  * @retval HAL status
+  */
+
+HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_EVENT_SOURCE(EventSource));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  /* Change the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Set the event sources */
+  htim->Instance->EGR = EventSource;
+
+  /* Change the TIM state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the OCRef clear feature
+  * @param  htim TIM handle
+  * @param  sClearInputConfig pointer to a TIM_ClearInputConfigTypeDef structure that
+  *         contains the OCREF clear feature and parameters for the TIM peripheral.
+  * @param  Channel specifies the TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  *            @arg TIM_CHANNEL_4: TIM Channel 4
+  *            @arg TIM_CHANNEL_5: TIM Channel 5
+  *            @arg TIM_CHANNEL_6: TIM Channel 6
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim,
+                                           const TIM_ClearInputConfigTypeDef *sClearInputConfig,
+                                           uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_OCXREF_CLEAR_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  switch (sClearInputConfig->ClearInputSource)
+  {
+    case TIM_CLEARINPUTSOURCE_NONE:
+    {
+      /* Clear the OCREF clear selection bit and the the ETR Bits */
+      CLEAR_BIT(htim->Instance->SMCR, (TIM_SMCR_OCCS | TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP));
+
+      /* Clear TIMx_AF1_OCREF_CLR (reset value) */
+      CLEAR_BIT(htim->Instance->AF1, TIM1_AF1_ETRSEL);
+      break;
+    }
+    case TIM_CLEARINPUTSOURCE_COMP1:
+    case TIM_CLEARINPUTSOURCE_COMP2:
+    {
+      /* Clear the OCREF clear selection bit */
+      CLEAR_BIT(htim->Instance->SMCR, TIM_SMCR_OCCS);
+
+      /* OCREF_CLR_INT is connected to COMPx output */
+      MODIFY_REG(htim->Instance->AF1, TIM1_AF1_ETRSEL, sClearInputConfig->ClearInputSource);
+      break;
+    }
+
+    case TIM_CLEARINPUTSOURCE_ETR:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CLEARINPUT_POLARITY(sClearInputConfig->ClearInputPolarity));
+      assert_param(IS_TIM_CLEARINPUT_PRESCALER(sClearInputConfig->ClearInputPrescaler));
+      assert_param(IS_TIM_CLEARINPUT_FILTER(sClearInputConfig->ClearInputFilter));
+
+      /* When OCRef clear feature is used with ETR source, ETR prescaler must be off */
+      if (sClearInputConfig->ClearInputPrescaler != TIM_CLEARINPUTPRESCALER_DIV1)
+      {
+        htim->State = HAL_TIM_STATE_READY;
+        __HAL_UNLOCK(htim);
+        return HAL_ERROR;
+      }
+
+      TIM_ETR_SetConfig(htim->Instance,
+                        sClearInputConfig->ClearInputPrescaler,
+                        sClearInputConfig->ClearInputPolarity,
+                        sClearInputConfig->ClearInputFilter);
+
+      /* Set the OCREF clear selection bit */
+      SET_BIT(htim->Instance->SMCR, TIM_SMCR_OCCS);
+
+      /* Clear TIMx_AF1_OCREF_CLR (reset value) */
+      CLEAR_BIT(htim->Instance->AF1, TIM1_AF1_ETRSEL);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    switch (Channel)
+    {
+      case TIM_CHANNEL_1:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 1 */
+          SET_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC1CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 1 */
+          CLEAR_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC1CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_2:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 2 */
+          SET_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC2CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 2 */
+          CLEAR_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC2CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_3:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 3 */
+          SET_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC3CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 3 */
+          CLEAR_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC3CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_4:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 4 */
+          SET_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC4CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 4 */
+          CLEAR_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC4CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_5:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 5 */
+          SET_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC5CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 5 */
+          CLEAR_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC5CE);
+        }
+        break;
+      }
+      case TIM_CHANNEL_6:
+      {
+        if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+        {
+          /* Enable the OCREF clear feature for Channel 6 */
+          SET_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC6CE);
+        }
+        else
+        {
+          /* Disable the OCREF clear feature for Channel 6 */
+          CLEAR_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC6CE);
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief   Configures the clock source to be used
+  * @param  htim TIM handle
+  * @param  sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that
+  *         contains the clock source information for the TIM peripheral.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CLOCKSOURCE(sClockSourceConfig->ClockSource));
+
+  /* Reset the SMS, TS, ECE, ETPS and ETRF bits */
+  tmpsmcr = htim->Instance->SMCR;
+  tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
+  tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+  htim->Instance->SMCR = tmpsmcr;
+
+  switch (sClockSourceConfig->ClockSource)
+  {
+    case TIM_CLOCKSOURCE_INTERNAL:
+    {
+      assert_param(IS_TIM_INSTANCE(htim->Instance));
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_ETRMODE1:
+    {
+      /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/
+      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
+
+      /* Check ETR input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      /* Configure the ETR Clock source */
+      TIM_ETR_SetConfig(htim->Instance,
+                        sClockSourceConfig->ClockPrescaler,
+                        sClockSourceConfig->ClockPolarity,
+                        sClockSourceConfig->ClockFilter);
+
+      /* Select the External clock mode1 and the ETRF trigger */
+      tmpsmcr = htim->Instance->SMCR;
+      tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1);
+      /* Write to TIMx SMCR */
+      htim->Instance->SMCR = tmpsmcr;
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_ETRMODE2:
+    {
+      /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/
+      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance));
+
+      /* Check ETR input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      /* Configure the ETR Clock source */
+      TIM_ETR_SetConfig(htim->Instance,
+                        sClockSourceConfig->ClockPrescaler,
+                        sClockSourceConfig->ClockPolarity,
+                        sClockSourceConfig->ClockFilter);
+      /* Enable the External clock mode2 */
+      htim->Instance->SMCR |= TIM_SMCR_ECE;
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_TI1:
+    {
+      /* Check whether or not the timer instance supports external clock mode 1 */
+      assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+      /* Check TI1 input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      TIM_TI1_ConfigInputStage(htim->Instance,
+                               sClockSourceConfig->ClockPolarity,
+                               sClockSourceConfig->ClockFilter);
+      TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1);
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_TI2:
+    {
+      /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/
+      assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+      /* Check TI2 input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      TIM_TI2_ConfigInputStage(htim->Instance,
+                               sClockSourceConfig->ClockPolarity,
+                               sClockSourceConfig->ClockFilter);
+      TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2);
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_TI1ED:
+    {
+      /* Check whether or not the timer instance supports external clock mode 1 */
+      assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+      /* Check TI1 input conditioning related parameters */
+      assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+      assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+      TIM_TI1_ConfigInputStage(htim->Instance,
+                               sClockSourceConfig->ClockPolarity,
+                               sClockSourceConfig->ClockFilter);
+      TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED);
+      break;
+    }
+
+    case TIM_CLOCKSOURCE_ITR0:
+    case TIM_CLOCKSOURCE_ITR1:
+    case TIM_CLOCKSOURCE_ITR2:
+    case TIM_CLOCKSOURCE_ITR3:
+    {
+      /* Check whether or not the timer instance supports internal trigger input */
+      assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
+
+      TIM_ITRx_SetConfig(htim->Instance, sClockSourceConfig->ClockSource);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Selects the signal connected to the TI1 input: direct from CH1_input
+  *         or a XOR combination between CH1_input, CH2_input & CH3_input
+  * @param  htim TIM handle.
+  * @param  TI1_Selection Indicate whether or not channel 1 is connected to the
+  *         output of a XOR gate.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TI1SELECTION_CH1: The TIMx_CH1 pin is connected to TI1 input
+  *            @arg TIM_TI1SELECTION_XORCOMBINATION: The TIMx_CH1, CH2 and CH3
+  *            pins are connected to the TI1 input (XOR combination)
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection)
+{
+  uint32_t tmpcr2;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_TI1SELECTION(TI1_Selection));
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 = htim->Instance->CR2;
+
+  /* Reset the TI1 selection */
+  tmpcr2 &= ~TIM_CR2_TI1S;
+
+  /* Set the TI1 selection */
+  tmpcr2 |= TI1_Selection;
+
+  /* Write to TIMxCR2 */
+  htim->Instance->CR2 = tmpcr2;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIM in Slave mode
+  * @param  htim TIM handle.
+  * @param  sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that
+  *         contains the selected trigger (internal trigger input, filtered
+  *         timer input or external trigger input) and the Slave mode
+  *         (Disable, Reset, Gated, Trigger, External clock mode 1).
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode));
+  assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  if (TIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+    __HAL_UNLOCK(htim);
+    return HAL_ERROR;
+  }
+
+  /* Disable Trigger Interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_TRIGGER);
+
+  /* Disable Trigger DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER);
+
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIM in Slave mode in interrupt mode
+  * @param  htim TIM handle.
+  * @param  sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that
+  *         contains the selected trigger (internal trigger input, filtered
+  *         timer input or external trigger input) and the Slave mode
+  *         (Disable, Reset, Gated, Trigger, External clock mode 1).
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim,
+                                                const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode));
+  assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  if (TIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+    __HAL_UNLOCK(htim);
+    return HAL_ERROR;
+  }
+
+  /* Enable Trigger Interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_TRIGGER);
+
+  /* Disable Trigger DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER);
+
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Read the captured value from Capture Compare unit
+  * @param  htim TIM handle.
+  * @param  Channel TIM Channels to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
+  * @retval Captured value
+  */
+uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpreg = 0U;
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+      /* Return the capture 1 value */
+      tmpreg =  htim->Instance->CCR1;
+
+      break;
+    }
+    case TIM_CHANNEL_2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+      /* Return the capture 2 value */
+      tmpreg =   htim->Instance->CCR2;
+
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+      /* Return the capture 3 value */
+      tmpreg =   htim->Instance->CCR3;
+
+      break;
+    }
+
+    case TIM_CHANNEL_4:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+      /* Return the capture 4 value */
+      tmpreg =   htim->Instance->CCR4;
+
+      break;
+    }
+
+    default:
+      break;
+  }
+
+  return tmpreg;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions
+  *  @brief    TIM Callbacks functions
+  *
+@verbatim
+  ==============================================================================
+                        ##### TIM Callbacks functions #####
+  ==============================================================================
+ [..]
+   This section provides TIM callback functions:
+   (+) TIM Period elapsed callback
+   (+) TIM Output Compare callback
+   (+) TIM Input capture callback
+   (+) TIM Trigger callback
+   (+) TIM Error callback
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Period elapsed callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Period elapsed half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PeriodElapsedHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Output Compare callback in non-blocking mode
+  * @param  htim TIM OC handle
+  * @retval None
+  */
+__weak void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_OC_DelayElapsedCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Input Capture callback in non-blocking mode
+  * @param  htim TIM IC handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_CaptureCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Input Capture half complete callback in non-blocking mode
+  * @param  htim TIM IC handle
+  * @retval None
+  */
+__weak void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_IC_CaptureHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  PWM Pulse finished callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_PulseFinishedCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  PWM Pulse finished half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_PWM_PulseFinishedHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_PWM_PulseFinishedHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Hall Trigger detection callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_TriggerCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Hall Trigger detection half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_TriggerHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_TriggerHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Timer error callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIM_ErrorCallback could be implemented in the user file
+   */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  Register a User TIM callback to be used instead of the weak predefined callback
+  * @param htim tim handle
+  * @param CallbackID ID of the callback to be registered
+  *        This parameter can be one of the following values:
+  *          @arg @ref HAL_TIM_BASE_MSPINIT_CB_ID Base MspInit Callback ID
+  *          @arg @ref HAL_TIM_BASE_MSPDEINIT_CB_ID Base MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPINIT_CB_ID IC MspInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPDEINIT_CB_ID IC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPINIT_CB_ID OC MspInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPDEINIT_CB_ID OC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPINIT_CB_ID PWM MspInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPDEINIT_CB_ID PWM MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPINIT_CB_ID One Pulse MspInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID One Pulse MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPINIT_CB_ID Encoder MspInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPDEINIT_CB_ID Encoder MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID Hall Sensor MspInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID Hall Sensor MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_CB_ID Period Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID Period Elapsed half complete Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_CB_ID Trigger Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_HALF_CB_ID Trigger half complete Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_CB_ID Input Capture Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_HALF_CB_ID Input Capture half complete Callback ID
+  *          @arg @ref HAL_TIM_OC_DELAY_ELAPSED_CB_ID Output Compare Delay Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_CB_ID PWM Pulse Finished Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID PWM Pulse Finished half complete Callback ID
+  *          @arg @ref HAL_TIM_ERROR_CB_ID Error Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_CB_ID Commutation Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_HALF_CB_ID Commutation half complete Callback ID
+  *          @arg @ref HAL_TIM_BREAK_CB_ID Break Callback ID
+  *          @arg @ref HAL_TIM_BREAK2_CB_ID Break2 Callback ID
+  *          @param pCallback pointer to the callback function
+  *          @retval status
+  */
+HAL_StatusTypeDef HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID,
+                                           pTIM_CallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  if (htim->State == HAL_TIM_STATE_READY)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        htim->Base_MspInitCallback                 = pCallback;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        htim->Base_MspDeInitCallback               = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        htim->IC_MspInitCallback                   = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        htim->IC_MspDeInitCallback                 = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        htim->OC_MspInitCallback                   = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        htim->OC_MspDeInitCallback                 = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        htim->PWM_MspInitCallback                  = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        htim->PWM_MspDeInitCallback                = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        htim->OnePulse_MspInitCallback             = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        htim->OnePulse_MspDeInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        htim->Encoder_MspInitCallback              = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        htim->Encoder_MspDeInitCallback            = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        htim->HallSensor_MspInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        htim->HallSensor_MspDeInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+        htim->PeriodElapsedCallback                = pCallback;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+        htim->PeriodElapsedHalfCpltCallback        = pCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_CB_ID :
+        htim->TriggerCallback                      = pCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_HALF_CB_ID :
+        htim->TriggerHalfCpltCallback              = pCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_CB_ID :
+        htim->IC_CaptureCallback                   = pCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+        htim->IC_CaptureHalfCpltCallback           = pCallback;
+        break;
+
+      case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+        htim->OC_DelayElapsedCallback              = pCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+        htim->PWM_PulseFinishedCallback            = pCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+        htim->PWM_PulseFinishedHalfCpltCallback    = pCallback;
+        break;
+
+      case HAL_TIM_ERROR_CB_ID :
+        htim->ErrorCallback                        = pCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_CB_ID :
+        htim->CommutationCallback                  = pCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_HALF_CB_ID :
+        htim->CommutationHalfCpltCallback          = pCallback;
+        break;
+
+      case HAL_TIM_BREAK_CB_ID :
+        htim->BreakCallback                        = pCallback;
+        break;
+
+      case HAL_TIM_BREAK2_CB_ID :
+        htim->Break2Callback                       = pCallback;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        htim->Base_MspInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        htim->Base_MspDeInitCallback       = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        htim->IC_MspInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        htim->IC_MspDeInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        htim->OC_MspInitCallback           = pCallback;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        htim->OC_MspDeInitCallback         = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        htim->PWM_MspInitCallback          = pCallback;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        htim->PWM_MspDeInitCallback        = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        htim->OnePulse_MspInitCallback     = pCallback;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        htim->OnePulse_MspDeInitCallback   = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        htim->Encoder_MspInitCallback      = pCallback;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        htim->Encoder_MspDeInitCallback    = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        htim->HallSensor_MspInitCallback   = pCallback;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        htim->HallSensor_MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Return error status */
+    status = HAL_ERROR;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Unregister a TIM callback
+  *         TIM callback is redirected to the weak predefined callback
+  * @param htim tim handle
+  * @param CallbackID ID of the callback to be unregistered
+  *        This parameter can be one of the following values:
+  *          @arg @ref HAL_TIM_BASE_MSPINIT_CB_ID Base MspInit Callback ID
+  *          @arg @ref HAL_TIM_BASE_MSPDEINIT_CB_ID Base MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPINIT_CB_ID IC MspInit Callback ID
+  *          @arg @ref HAL_TIM_IC_MSPDEINIT_CB_ID IC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPINIT_CB_ID OC MspInit Callback ID
+  *          @arg @ref HAL_TIM_OC_MSPDEINIT_CB_ID OC MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPINIT_CB_ID PWM MspInit Callback ID
+  *          @arg @ref HAL_TIM_PWM_MSPDEINIT_CB_ID PWM MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPINIT_CB_ID One Pulse MspInit Callback ID
+  *          @arg @ref HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID One Pulse MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPINIT_CB_ID Encoder MspInit Callback ID
+  *          @arg @ref HAL_TIM_ENCODER_MSPDEINIT_CB_ID Encoder MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID Hall Sensor MspInit Callback ID
+  *          @arg @ref HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID Hall Sensor MspDeInit Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_CB_ID Period Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID Period Elapsed half complete Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_CB_ID Trigger Callback ID
+  *          @arg @ref HAL_TIM_TRIGGER_HALF_CB_ID Trigger half complete Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_CB_ID Input Capture Callback ID
+  *          @arg @ref HAL_TIM_IC_CAPTURE_HALF_CB_ID Input Capture half complete Callback ID
+  *          @arg @ref HAL_TIM_OC_DELAY_ELAPSED_CB_ID Output Compare Delay Elapsed Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_CB_ID PWM Pulse Finished Callback ID
+  *          @arg @ref HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID PWM Pulse Finished half complete Callback ID
+  *          @arg @ref HAL_TIM_ERROR_CB_ID Error Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_CB_ID Commutation Callback ID
+  *          @arg @ref HAL_TIM_COMMUTATION_HALF_CB_ID Commutation half complete Callback ID
+  *          @arg @ref HAL_TIM_BREAK_CB_ID Break Callback ID
+  *          @arg @ref HAL_TIM_BREAK2_CB_ID Break2 Callback ID
+  *          @retval status
+  */
+HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (htim->State == HAL_TIM_STATE_READY)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        /* Legacy weak Base MspInit Callback */
+        htim->Base_MspInitCallback              = HAL_TIM_Base_MspInit;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        /* Legacy weak Base Msp DeInit Callback */
+        htim->Base_MspDeInitCallback            = HAL_TIM_Base_MspDeInit;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        /* Legacy weak IC Msp Init Callback */
+        htim->IC_MspInitCallback                = HAL_TIM_IC_MspInit;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        /* Legacy weak IC Msp DeInit Callback */
+        htim->IC_MspDeInitCallback              = HAL_TIM_IC_MspDeInit;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        /* Legacy weak OC Msp Init Callback */
+        htim->OC_MspInitCallback                = HAL_TIM_OC_MspInit;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        /* Legacy weak OC Msp DeInit Callback */
+        htim->OC_MspDeInitCallback              = HAL_TIM_OC_MspDeInit;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        /* Legacy weak PWM Msp Init Callback */
+        htim->PWM_MspInitCallback               = HAL_TIM_PWM_MspInit;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        /* Legacy weak PWM Msp DeInit Callback */
+        htim->PWM_MspDeInitCallback             = HAL_TIM_PWM_MspDeInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        /* Legacy weak One Pulse Msp Init Callback */
+        htim->OnePulse_MspInitCallback          = HAL_TIM_OnePulse_MspInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        /* Legacy weak One Pulse Msp DeInit Callback */
+        htim->OnePulse_MspDeInitCallback        = HAL_TIM_OnePulse_MspDeInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        /* Legacy weak Encoder Msp Init Callback */
+        htim->Encoder_MspInitCallback           = HAL_TIM_Encoder_MspInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        /* Legacy weak Encoder Msp DeInit Callback */
+        htim->Encoder_MspDeInitCallback         = HAL_TIM_Encoder_MspDeInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp Init Callback */
+        htim->HallSensor_MspInitCallback        = HAL_TIMEx_HallSensor_MspInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp DeInit Callback */
+        htim->HallSensor_MspDeInitCallback      = HAL_TIMEx_HallSensor_MspDeInit;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+        /* Legacy weak Period Elapsed Callback */
+        htim->PeriodElapsedCallback             = HAL_TIM_PeriodElapsedCallback;
+        break;
+
+      case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+        /* Legacy weak Period Elapsed half complete Callback */
+        htim->PeriodElapsedHalfCpltCallback     = HAL_TIM_PeriodElapsedHalfCpltCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_CB_ID :
+        /* Legacy weak Trigger Callback */
+        htim->TriggerCallback                   = HAL_TIM_TriggerCallback;
+        break;
+
+      case HAL_TIM_TRIGGER_HALF_CB_ID :
+        /* Legacy weak Trigger half complete Callback */
+        htim->TriggerHalfCpltCallback           = HAL_TIM_TriggerHalfCpltCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_CB_ID :
+        /* Legacy weak IC Capture Callback */
+        htim->IC_CaptureCallback                = HAL_TIM_IC_CaptureCallback;
+        break;
+
+      case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+        /* Legacy weak IC Capture half complete Callback */
+        htim->IC_CaptureHalfCpltCallback        = HAL_TIM_IC_CaptureHalfCpltCallback;
+        break;
+
+      case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+        /* Legacy weak OC Delay Elapsed Callback */
+        htim->OC_DelayElapsedCallback           = HAL_TIM_OC_DelayElapsedCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+        /* Legacy weak PWM Pulse Finished Callback */
+        htim->PWM_PulseFinishedCallback         = HAL_TIM_PWM_PulseFinishedCallback;
+        break;
+
+      case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+        /* Legacy weak PWM Pulse Finished half complete Callback */
+        htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback;
+        break;
+
+      case HAL_TIM_ERROR_CB_ID :
+        /* Legacy weak Error Callback */
+        htim->ErrorCallback                     = HAL_TIM_ErrorCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_CB_ID :
+        /* Legacy weak Commutation Callback */
+        htim->CommutationCallback               = HAL_TIMEx_CommutCallback;
+        break;
+
+      case HAL_TIM_COMMUTATION_HALF_CB_ID :
+        /* Legacy weak Commutation half complete Callback */
+        htim->CommutationHalfCpltCallback       = HAL_TIMEx_CommutHalfCpltCallback;
+        break;
+
+      case HAL_TIM_BREAK_CB_ID :
+        /* Legacy weak Break Callback */
+        htim->BreakCallback                     = HAL_TIMEx_BreakCallback;
+        break;
+
+      case HAL_TIM_BREAK2_CB_ID :
+        /* Legacy weak Break2 Callback */
+        htim->Break2Callback                    = HAL_TIMEx_Break2Callback;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    switch (CallbackID)
+    {
+      case HAL_TIM_BASE_MSPINIT_CB_ID :
+        /* Legacy weak Base MspInit Callback */
+        htim->Base_MspInitCallback         = HAL_TIM_Base_MspInit;
+        break;
+
+      case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+        /* Legacy weak Base Msp DeInit Callback */
+        htim->Base_MspDeInitCallback       = HAL_TIM_Base_MspDeInit;
+        break;
+
+      case HAL_TIM_IC_MSPINIT_CB_ID :
+        /* Legacy weak IC Msp Init Callback */
+        htim->IC_MspInitCallback           = HAL_TIM_IC_MspInit;
+        break;
+
+      case HAL_TIM_IC_MSPDEINIT_CB_ID :
+        /* Legacy weak IC Msp DeInit Callback */
+        htim->IC_MspDeInitCallback         = HAL_TIM_IC_MspDeInit;
+        break;
+
+      case HAL_TIM_OC_MSPINIT_CB_ID :
+        /* Legacy weak OC Msp Init Callback */
+        htim->OC_MspInitCallback           = HAL_TIM_OC_MspInit;
+        break;
+
+      case HAL_TIM_OC_MSPDEINIT_CB_ID :
+        /* Legacy weak OC Msp DeInit Callback */
+        htim->OC_MspDeInitCallback         = HAL_TIM_OC_MspDeInit;
+        break;
+
+      case HAL_TIM_PWM_MSPINIT_CB_ID :
+        /* Legacy weak PWM Msp Init Callback */
+        htim->PWM_MspInitCallback          = HAL_TIM_PWM_MspInit;
+        break;
+
+      case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+        /* Legacy weak PWM Msp DeInit Callback */
+        htim->PWM_MspDeInitCallback        = HAL_TIM_PWM_MspDeInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+        /* Legacy weak One Pulse Msp Init Callback */
+        htim->OnePulse_MspInitCallback     = HAL_TIM_OnePulse_MspInit;
+        break;
+
+      case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+        /* Legacy weak One Pulse Msp DeInit Callback */
+        htim->OnePulse_MspDeInitCallback   = HAL_TIM_OnePulse_MspDeInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+        /* Legacy weak Encoder Msp Init Callback */
+        htim->Encoder_MspInitCallback      = HAL_TIM_Encoder_MspInit;
+        break;
+
+      case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+        /* Legacy weak Encoder Msp DeInit Callback */
+        htim->Encoder_MspDeInitCallback    = HAL_TIM_Encoder_MspDeInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp Init Callback */
+        htim->HallSensor_MspInitCallback   = HAL_TIMEx_HallSensor_MspInit;
+        break;
+
+      case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+        /* Legacy weak Hall Sensor Msp DeInit Callback */
+        htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+        break;
+
+      default :
+        /* Return error status */
+        status = HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Return error status */
+    status = HAL_ERROR;
+  }
+
+  return status;
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Exported_Functions_Group10 TIM Peripheral State functions
+  *  @brief   TIM Peripheral State functions
+  *
+@verbatim
+  ==============================================================================
+                        ##### Peripheral State functions #####
+  ==============================================================================
+    [..]
+    This subsection permits to get in run-time the status of the peripheral
+    and the data flow.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the TIM Base handle state.
+  * @param  htim TIM Base handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM OC handle state.
+  * @param  htim TIM Output Compare handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM PWM handle state.
+  * @param  htim TIM handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM Input Capture handle state.
+  * @param  htim TIM IC handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM One Pulse Mode handle state.
+  * @param  htim TIM OPM handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM Encoder Mode handle state.
+  * @param  htim TIM Encoder Interface handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return the TIM Encoder Mode handle state.
+  * @param  htim TIM handle
+  * @retval Active channel
+  */
+HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim)
+{
+  return htim->Channel;
+}
+
+/**
+  * @brief  Return actual state of the TIM channel.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  *            @arg TIM_CHANNEL_4: TIM Channel 4
+  *            @arg TIM_CHANNEL_5: TIM Channel 5
+  *            @arg TIM_CHANNEL_6: TIM Channel 6
+  * @retval TIM Channel state
+  */
+HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim,  uint32_t Channel)
+{
+  HAL_TIM_ChannelStateTypeDef channel_state;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+  channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+
+  return channel_state;
+}
+
+/**
+  * @brief  Return actual state of a DMA burst operation.
+  * @param  htim TIM handle
+  * @retval DMA burst state
+  */
+HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+
+  return htim->DMABurstState;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Private_Functions TIM Private Functions
+  * @{
+  */
+
+/**
+  * @brief  TIM DMA error callback
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMAError(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+    TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    htim->State = HAL_TIM_STATE_READY;
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->ErrorCallback(htim);
+#else
+  HAL_TIM_ErrorCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Delay Pulse complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PWM_PulseFinishedCallback(htim);
+#else
+  HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Delay Pulse half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMADelayPulseHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PWM_PulseFinishedHalfCpltCallback(htim);
+#else
+  HAL_TIM_PWM_PulseFinishedHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Capture complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->IC_CaptureCallback(htim);
+#else
+  HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Capture half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIM_DMACaptureHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->IC_CaptureHalfCpltCallback(htim);
+#else
+  HAL_TIM_IC_CaptureHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA Period Elapse complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (htim->hdma[TIM_DMA_ID_UPDATE]->Init.Mode == DMA_NORMAL)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PeriodElapsedCallback(htim);
+#else
+  HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Period Elapse half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMAPeriodElapsedHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PeriodElapsedHalfCpltCallback(htim);
+#else
+  HAL_TIM_PeriodElapsedHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Trigger callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (htim->hdma[TIM_DMA_ID_TRIGGER]->Init.Mode == DMA_NORMAL)
+  {
+    htim->State = HAL_TIM_STATE_READY;
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->TriggerCallback(htim);
+#else
+  HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Trigger half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->TriggerHalfCpltCallback(htim);
+#else
+  HAL_TIM_TriggerHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  Time Base configuration
+  * @param  TIMx TIM peripheral
+  * @param  Structure TIM Base configuration structure
+  * @retval None
+  */
+void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure)
+{
+  uint32_t tmpcr1;
+  tmpcr1 = TIMx->CR1;
+
+  /* Set TIM Time Base Unit parameters ---------------------------------------*/
+  if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
+  {
+    /* Select the Counter Mode */
+    tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
+    tmpcr1 |= Structure->CounterMode;
+  }
+
+  if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
+  {
+    /* Set the clock division */
+    tmpcr1 &= ~TIM_CR1_CKD;
+    tmpcr1 |= (uint32_t)Structure->ClockDivision;
+  }
+
+  /* Set the auto-reload preload */
+  MODIFY_REG(tmpcr1, TIM_CR1_ARPE, Structure->AutoReloadPreload);
+
+  TIMx->CR1 = tmpcr1;
+
+  /* Set the Autoreload value */
+  TIMx->ARR = (uint32_t)Structure->Period ;
+
+  /* Set the Prescaler value */
+  TIMx->PSC = Structure->Prescaler;
+
+  if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
+  {
+    /* Set the Repetition Counter value */
+    TIMx->RCR = Structure->RepetitionCounter;
+  }
+
+  /* Generate an update event to reload the Prescaler
+     and the repetition counter (only for advanced timer) value immediately */
+  TIMx->EGR = TIM_EGR_UG;
+}
+
+/**
+  * @brief  Timer Output Compare 1 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Disable the Channel 1: Reset the CC1E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC1E;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR1 register value */
+  tmpccmrx = TIMx->CCMR1;
+
+  /* Reset the Output Compare Mode Bits */
+  tmpccmrx &= ~TIM_CCMR1_OC1M;
+  tmpccmrx &= ~TIM_CCMR1_CC1S;
+  /* Select the Output Compare Mode */
+  tmpccmrx |= OC_Config->OCMode;
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC1P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= OC_Config->OCPolarity;
+
+  if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+    /* Reset the Output N Polarity level */
+    tmpccer &= ~TIM_CCER_CC1NP;
+    /* Set the Output N Polarity */
+    tmpccer |= OC_Config->OCNPolarity;
+    /* Reset the Output N State */
+    tmpccer &= ~TIM_CCER_CC1NE;
+  }
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare and Output Compare N IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS1;
+    tmpcr2 &= ~TIM_CR2_OIS1N;
+    /* Set the Output Idle state */
+    tmpcr2 |= OC_Config->OCIdleState;
+    /* Set the Output N Idle state */
+    tmpcr2 |= OC_Config->OCNIdleState;
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR1 */
+  TIMx->CCMR1 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR1 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 2 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Disable the Channel 2: Reset the CC2E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC2E;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR1 register value */
+  tmpccmrx = TIMx->CCMR1;
+
+  /* Reset the Output Compare mode and Capture/Compare selection Bits */
+  tmpccmrx &= ~TIM_CCMR1_OC2M;
+  tmpccmrx &= ~TIM_CCMR1_CC2S;
+
+  /* Select the Output Compare Mode */
+  tmpccmrx |= (OC_Config->OCMode << 8U);
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC2P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 4U);
+
+  if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2))
+  {
+    assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+    /* Reset the Output N Polarity level */
+    tmpccer &= ~TIM_CCER_CC2NP;
+    /* Set the Output N Polarity */
+    tmpccer |= (OC_Config->OCNPolarity << 4U);
+    /* Reset the Output N State */
+    tmpccer &= ~TIM_CCER_CC2NE;
+
+  }
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare and Output Compare N IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS2;
+    tmpcr2 &= ~TIM_CR2_OIS2N;
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 2U);
+    /* Set the Output N Idle state */
+    tmpcr2 |= (OC_Config->OCNIdleState << 2U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR1 */
+  TIMx->CCMR1 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR2 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 3 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Disable the Channel 3: Reset the CC2E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC3E;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR2 register value */
+  tmpccmrx = TIMx->CCMR2;
+
+  /* Reset the Output Compare mode and Capture/Compare selection Bits */
+  tmpccmrx &= ~TIM_CCMR2_OC3M;
+  tmpccmrx &= ~TIM_CCMR2_CC3S;
+  /* Select the Output Compare Mode */
+  tmpccmrx |= OC_Config->OCMode;
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC3P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 8U);
+
+  if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3))
+  {
+    assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+    /* Reset the Output N Polarity level */
+    tmpccer &= ~TIM_CCER_CC3NP;
+    /* Set the Output N Polarity */
+    tmpccer |= (OC_Config->OCNPolarity << 8U);
+    /* Reset the Output N State */
+    tmpccer &= ~TIM_CCER_CC3NE;
+  }
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare and Output Compare N IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS3;
+    tmpcr2 &= ~TIM_CR2_OIS3N;
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 4U);
+    /* Set the Output N Idle state */
+    tmpcr2 |= (OC_Config->OCNIdleState << 4U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR2 */
+  TIMx->CCMR2 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR3 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 4 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Disable the Channel 4: Reset the CC4E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC4E;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+
+  /* Get the TIMx CCMR2 register value */
+  tmpccmrx = TIMx->CCMR2;
+
+  /* Reset the Output Compare mode and Capture/Compare selection Bits */
+  tmpccmrx &= ~TIM_CCMR2_OC4M;
+  tmpccmrx &= ~TIM_CCMR2_CC4S;
+
+  /* Select the Output Compare Mode */
+  tmpccmrx |= (OC_Config->OCMode << 8U);
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC4P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 12U);
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Check parameters */
+    assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+    /* Reset the Output Compare IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS4;
+
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 6U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR2 */
+  TIMx->CCMR2 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR4 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 5 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx,
+                              const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Disable the output: Reset the CCxE Bit */
+  TIMx->CCER &= ~TIM_CCER_CC5E;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+  /* Get the TIMx CCMR1 register value */
+  tmpccmrx = TIMx->CCMR3;
+
+  /* Reset the Output Compare Mode Bits */
+  tmpccmrx &= ~(TIM_CCMR3_OC5M);
+  /* Select the Output Compare Mode */
+  tmpccmrx |= OC_Config->OCMode;
+
+  /* Reset the Output Polarity level */
+  tmpccer &= ~TIM_CCER_CC5P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 16U);
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Reset the Output Compare IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS5;
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 8U);
+  }
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR3 */
+  TIMx->CCMR3 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR5 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Timer Output Compare 6 configuration
+  * @param  TIMx to select the TIM peripheral
+  * @param  OC_Config The output configuration structure
+  * @retval None
+  */
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx,
+                              const TIM_OC_InitTypeDef *OC_Config)
+{
+  uint32_t tmpccmrx;
+  uint32_t tmpccer;
+  uint32_t tmpcr2;
+
+  /* Disable the output: Reset the CCxE Bit */
+  TIMx->CCER &= ~TIM_CCER_CC6E;
+
+  /* Get the TIMx CCER register value */
+  tmpccer = TIMx->CCER;
+  /* Get the TIMx CR2 register value */
+  tmpcr2 =  TIMx->CR2;
+  /* Get the TIMx CCMR1 register value */
+  tmpccmrx = TIMx->CCMR3;
+
+  /* Reset the Output Compare Mode Bits */
+  tmpccmrx &= ~(TIM_CCMR3_OC6M);
+  /* Select the Output Compare Mode */
+  tmpccmrx |= (OC_Config->OCMode << 8U);
+
+  /* Reset the Output Polarity level */
+  tmpccer &= (uint32_t)~TIM_CCER_CC6P;
+  /* Set the Output Compare Polarity */
+  tmpccer |= (OC_Config->OCPolarity << 20U);
+
+  if (IS_TIM_BREAK_INSTANCE(TIMx))
+  {
+    /* Reset the Output Compare IDLE State */
+    tmpcr2 &= ~TIM_CR2_OIS6;
+    /* Set the Output Idle state */
+    tmpcr2 |= (OC_Config->OCIdleState << 10U);
+  }
+
+  /* Write to TIMx CR2 */
+  TIMx->CR2 = tmpcr2;
+
+  /* Write to TIMx CCMR3 */
+  TIMx->CCMR3 = tmpccmrx;
+
+  /* Set the Capture Compare Register value */
+  TIMx->CCR6 = OC_Config->Pulse;
+
+  /* Write to TIMx CCER */
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Slave Timer configuration function
+  * @param  htim TIM handle
+  * @param  sSlaveConfig Slave timer configuration
+  * @retval None
+  */
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+                                                  const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = htim->Instance->SMCR;
+
+  /* Reset the Trigger Selection Bits */
+  tmpsmcr &= ~TIM_SMCR_TS;
+  /* Set the Input Trigger source */
+  tmpsmcr |= sSlaveConfig->InputTrigger;
+
+  /* Reset the slave mode Bits */
+  tmpsmcr &= ~TIM_SMCR_SMS;
+  /* Set the slave mode */
+  tmpsmcr |= sSlaveConfig->SlaveMode;
+
+  /* Write to TIMx SMCR */
+  htim->Instance->SMCR = tmpsmcr;
+
+  /* Configure the trigger prescaler, filter, and polarity */
+  switch (sSlaveConfig->InputTrigger)
+  {
+    case TIM_TS_ETRF:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERPRESCALER(sSlaveConfig->TriggerPrescaler));
+      assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+      /* Configure the ETR Trigger source */
+      TIM_ETR_SetConfig(htim->Instance,
+                        sSlaveConfig->TriggerPrescaler,
+                        sSlaveConfig->TriggerPolarity,
+                        sSlaveConfig->TriggerFilter);
+      break;
+    }
+
+    case TIM_TS_TI1F_ED:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+      if (sSlaveConfig->SlaveMode == TIM_SLAVEMODE_GATED)
+      {
+        return HAL_ERROR;
+      }
+
+      /* Disable the Channel 1: Reset the CC1E Bit */
+      tmpccer = htim->Instance->CCER;
+      htim->Instance->CCER &= ~TIM_CCER_CC1E;
+      tmpccmr1 = htim->Instance->CCMR1;
+
+      /* Set the filter */
+      tmpccmr1 &= ~TIM_CCMR1_IC1F;
+      tmpccmr1 |= ((sSlaveConfig->TriggerFilter) << 4U);
+
+      /* Write to TIMx CCMR1 and CCER registers */
+      htim->Instance->CCMR1 = tmpccmr1;
+      htim->Instance->CCER = tmpccer;
+      break;
+    }
+
+    case TIM_TS_TI1FP1:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+      /* Configure TI1 Filter and Polarity */
+      TIM_TI1_ConfigInputStage(htim->Instance,
+                               sSlaveConfig->TriggerPolarity,
+                               sSlaveConfig->TriggerFilter);
+      break;
+    }
+
+    case TIM_TS_TI2FP2:
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+      assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+      assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+      /* Configure TI2 Filter and Polarity */
+      TIM_TI2_ConfigInputStage(htim->Instance,
+                               sSlaveConfig->TriggerPolarity,
+                               sSlaveConfig->TriggerFilter);
+      break;
+    }
+
+    case TIM_TS_ITR0:
+    case TIM_TS_ITR1:
+    case TIM_TS_ITR2:
+    case TIM_TS_ITR3:
+    {
+      /* Check the parameter */
+      assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Configure the TI1 as Input.
+  * @param  TIMx to select the TIM peripheral.
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 1 is selected to be connected to IC1.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 1 is selected to be connected to IC2.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 1 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI2FP1
+  *       (on channel2 path) is used as the input signal. Therefore CCMR1 must be
+  *        protected against un-initialized filter and polarity values.
+  */
+void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                       uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 1: Reset the CC1E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC1E;
+  tmpccmr1 = TIMx->CCMR1;
+  tmpccer = TIMx->CCER;
+
+  /* Select the Input */
+  if (IS_TIM_CC2_INSTANCE(TIMx) != RESET)
+  {
+    tmpccmr1 &= ~TIM_CCMR1_CC1S;
+    tmpccmr1 |= TIM_ICSelection;
+  }
+  else
+  {
+    tmpccmr1 |= TIM_CCMR1_CC1S_0;
+  }
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC1F;
+  tmpccmr1 |= ((TIM_ICFilter << 4U) & TIM_CCMR1_IC1F);
+
+  /* Select the Polarity and set the CC1E Bit */
+  tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+  tmpccer |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the Polarity and Filter for TI1.
+  * @param  TIMx to select the TIM peripheral.
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  */
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 1: Reset the CC1E Bit */
+  tmpccer = TIMx->CCER;
+  TIMx->CCER &= ~TIM_CCER_CC1E;
+  tmpccmr1 = TIMx->CCMR1;
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC1F;
+  tmpccmr1 |= (TIM_ICFilter << 4U);
+
+  /* Select the Polarity and set the CC1E Bit */
+  tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+  tmpccer |= TIM_ICPolarity;
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the TI2 as Input.
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 2 is selected to be connected to IC2.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 2 is selected to be connected to IC1.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 2 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI1FP2
+  *       (on channel1 path) is used as the input signal. Therefore CCMR1 must be
+  *        protected against un-initialized filter and polarity values.
+  */
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 2: Reset the CC2E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC2E;
+  tmpccmr1 = TIMx->CCMR1;
+  tmpccer = TIMx->CCER;
+
+  /* Select the Input */
+  tmpccmr1 &= ~TIM_CCMR1_CC2S;
+  tmpccmr1 |= (TIM_ICSelection << 8U);
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC2F;
+  tmpccmr1 |= ((TIM_ICFilter << 12U) & TIM_CCMR1_IC2F);
+
+  /* Select the Polarity and set the CC2E Bit */
+  tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+  tmpccer |= ((TIM_ICPolarity << 4U) & (TIM_CCER_CC2P | TIM_CCER_CC2NP));
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1 ;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the Polarity and Filter for TI2.
+  * @param  TIMx to select the TIM peripheral.
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  */
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr1;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 2: Reset the CC2E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC2E;
+  tmpccmr1 = TIMx->CCMR1;
+  tmpccer = TIMx->CCER;
+
+  /* Set the filter */
+  tmpccmr1 &= ~TIM_CCMR1_IC2F;
+  tmpccmr1 |= (TIM_ICFilter << 12U);
+
+  /* Select the Polarity and set the CC2E Bit */
+  tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+  tmpccer |= (TIM_ICPolarity << 4U);
+
+  /* Write to TIMx CCMR1 and CCER registers */
+  TIMx->CCMR1 = tmpccmr1 ;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the TI3 as Input.
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 3 is selected to be connected to IC3.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 3 is selected to be connected to IC4.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 3 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @retval None
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI3FP4
+  *       (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+  *        protected against un-initialized filter and polarity values.
+  */
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr2;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 3: Reset the CC3E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC3E;
+  tmpccmr2 = TIMx->CCMR2;
+  tmpccer = TIMx->CCER;
+
+  /* Select the Input */
+  tmpccmr2 &= ~TIM_CCMR2_CC3S;
+  tmpccmr2 |= TIM_ICSelection;
+
+  /* Set the filter */
+  tmpccmr2 &= ~TIM_CCMR2_IC3F;
+  tmpccmr2 |= ((TIM_ICFilter << 4U) & TIM_CCMR2_IC3F);
+
+  /* Select the Polarity and set the CC3E Bit */
+  tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+  tmpccer |= ((TIM_ICPolarity << 8U) & (TIM_CCER_CC3P | TIM_CCER_CC3NP));
+
+  /* Write to TIMx CCMR2 and CCER registers */
+  TIMx->CCMR2 = tmpccmr2;
+  TIMx->CCER = tmpccer;
+}
+
+/**
+  * @brief  Configure the TI4 as Input.
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ICPolarity The Input Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICPOLARITY_RISING
+  *            @arg TIM_ICPOLARITY_FALLING
+  *            @arg TIM_ICPOLARITY_BOTHEDGE
+  * @param  TIM_ICSelection specifies the input to be used.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ICSELECTION_DIRECTTI: TIM Input 4 is selected to be connected to IC4.
+  *            @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 4 is selected to be connected to IC3.
+  *            @arg TIM_ICSELECTION_TRC: TIM Input 4 is selected to be connected to TRC.
+  * @param  TIM_ICFilter Specifies the Input Capture Filter.
+  *          This parameter must be a value between 0x00 and 0x0F.
+  * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI4FP3
+  *       (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+  *        protected against un-initialized filter and polarity values.
+  * @retval None
+  */
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+                              uint32_t TIM_ICFilter)
+{
+  uint32_t tmpccmr2;
+  uint32_t tmpccer;
+
+  /* Disable the Channel 4: Reset the CC4E Bit */
+  TIMx->CCER &= ~TIM_CCER_CC4E;
+  tmpccmr2 = TIMx->CCMR2;
+  tmpccer = TIMx->CCER;
+
+  /* Select the Input */
+  tmpccmr2 &= ~TIM_CCMR2_CC4S;
+  tmpccmr2 |= (TIM_ICSelection << 8U);
+
+  /* Set the filter */
+  tmpccmr2 &= ~TIM_CCMR2_IC4F;
+  tmpccmr2 |= ((TIM_ICFilter << 12U) & TIM_CCMR2_IC4F);
+
+  /* Select the Polarity and set the CC4E Bit */
+  tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP);
+  tmpccer |= ((TIM_ICPolarity << 12U) & (TIM_CCER_CC4P | TIM_CCER_CC4NP));
+
+  /* Write to TIMx CCMR2 and CCER registers */
+  TIMx->CCMR2 = tmpccmr2;
+  TIMx->CCER = tmpccer ;
+}
+
+/**
+  * @brief  Selects the Input Trigger source
+  * @param  TIMx to select the TIM peripheral
+  * @param  InputTriggerSource The Input Trigger source.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal Trigger 0
+  *            @arg TIM_TS_ITR1: Internal Trigger 1
+  *            @arg TIM_TS_ITR2: Internal Trigger 2
+  *            @arg TIM_TS_ITR3: Internal Trigger 3
+  *            @arg TIM_TS_TI1F_ED: TI1 Edge Detector
+  *            @arg TIM_TS_TI1FP1: Filtered Timer Input 1
+  *            @arg TIM_TS_TI2FP2: Filtered Timer Input 2
+  *            @arg TIM_TS_ETRF: External Trigger input
+  * @retval None
+  */
+static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint32_t InputTriggerSource)
+{
+  uint32_t tmpsmcr;
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = TIMx->SMCR;
+  /* Reset the TS Bits */
+  tmpsmcr &= ~TIM_SMCR_TS;
+  /* Set the Input Trigger source and the slave mode*/
+  tmpsmcr |= (InputTriggerSource | TIM_SLAVEMODE_EXTERNAL1);
+  /* Write to TIMx SMCR */
+  TIMx->SMCR = tmpsmcr;
+}
+/**
+  * @brief  Configures the TIMx External Trigger (ETR).
+  * @param  TIMx to select the TIM peripheral
+  * @param  TIM_ExtTRGPrescaler The external Trigger Prescaler.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ETRPRESCALER_DIV1: ETRP Prescaler OFF.
+  *            @arg TIM_ETRPRESCALER_DIV2: ETRP frequency divided by 2.
+  *            @arg TIM_ETRPRESCALER_DIV4: ETRP frequency divided by 4.
+  *            @arg TIM_ETRPRESCALER_DIV8: ETRP frequency divided by 8.
+  * @param  TIM_ExtTRGPolarity The external Trigger Polarity.
+  *          This parameter can be one of the following values:
+  *            @arg TIM_ETRPOLARITY_INVERTED: active low or falling edge active.
+  *            @arg TIM_ETRPOLARITY_NONINVERTED: active high or rising edge active.
+  * @param  ExtTRGFilter External Trigger Filter.
+  *          This parameter must be a value between 0x00 and 0x0F
+  * @retval None
+  */
+void TIM_ETR_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler,
+                       uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter)
+{
+  uint32_t tmpsmcr;
+
+  tmpsmcr = TIMx->SMCR;
+
+  /* Reset the ETR Bits */
+  tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+
+  /* Set the Prescaler, the Filter value and the Polarity */
+  tmpsmcr |= (uint32_t)(TIM_ExtTRGPrescaler | (TIM_ExtTRGPolarity | (ExtTRGFilter << 8U)));
+
+  /* Write to TIMx SMCR */
+  TIMx->SMCR = tmpsmcr;
+}
+
+/**
+  * @brief  Enables or disables the TIM Capture Compare Channel x.
+  * @param  TIMx to select the TIM peripheral
+  * @param  Channel specifies the TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  *            @arg TIM_CHANNEL_4: TIM Channel 4
+  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
+  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
+  * @param  ChannelState specifies the TIM Channel CCxE bit new state.
+  *          This parameter can be: TIM_CCx_ENABLE or TIM_CCx_DISABLE.
+  * @retval None
+  */
+void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
+{
+  uint32_t tmp;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+  assert_param(IS_TIM_CHANNELS(Channel));
+
+  tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
+
+  /* Reset the CCxE Bit */
+  TIMx->CCER &= ~tmp;
+
+  /* Set or reset the CCxE Bit */
+  TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+  * @brief  Reset interrupt callbacks to the legacy weak callbacks.
+  * @param  htim pointer to a TIM_HandleTypeDef structure that contains
+  *                the configuration information for TIM module.
+  * @retval None
+  */
+void TIM_ResetCallback(TIM_HandleTypeDef *htim)
+{
+  /* Reset the TIM callback to the legacy weak callbacks */
+  htim->PeriodElapsedCallback             = HAL_TIM_PeriodElapsedCallback;
+  htim->PeriodElapsedHalfCpltCallback     = HAL_TIM_PeriodElapsedHalfCpltCallback;
+  htim->TriggerCallback                   = HAL_TIM_TriggerCallback;
+  htim->TriggerHalfCpltCallback           = HAL_TIM_TriggerHalfCpltCallback;
+  htim->IC_CaptureCallback                = HAL_TIM_IC_CaptureCallback;
+  htim->IC_CaptureHalfCpltCallback        = HAL_TIM_IC_CaptureHalfCpltCallback;
+  htim->OC_DelayElapsedCallback           = HAL_TIM_OC_DelayElapsedCallback;
+  htim->PWM_PulseFinishedCallback         = HAL_TIM_PWM_PulseFinishedCallback;
+  htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback;
+  htim->ErrorCallback                     = HAL_TIM_ErrorCallback;
+  htim->CommutationCallback               = HAL_TIMEx_CommutCallback;
+  htim->CommutationHalfCpltCallback       = HAL_TIMEx_CommutHalfCpltCallback;
+  htim->BreakCallback                     = HAL_TIMEx_BreakCallback;
+  htim->Break2Callback                    = HAL_TIMEx_Break2Callback;
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+  * @}
+  */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

+ 2842 - 0
lib/adc/stm32wbxx_hal_tim_ex.c

@@ -0,0 +1,2842 @@
+/**
+  ******************************************************************************
+  * @file    stm32wbxx_hal_tim_ex.c
+  * @author  MCD Application Team
+  * @brief   TIM HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the Timer Extended peripheral:
+  *           + Time Hall Sensor Interface Initialization
+  *           + Time Hall Sensor Interface Start
+  *           + Time Complementary signal break and dead time configuration
+  *           + Time Master and Slave synchronization configuration
+  *           + Time Output Compare/PWM Channel Configuration (for channels 5 and 6)
+  *           + Time OCRef clear configuration
+  *           + Timer remapping capabilities configuration
+  ******************************************************************************
+  * @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
+  ==============================================================================
+                      ##### TIMER Extended features #####
+  ==============================================================================
+  [..]
+    The Timer Extended features include:
+    (#) Complementary outputs with programmable dead-time for :
+        (++) Output Compare
+        (++) PWM generation (Edge and Center-aligned Mode)
+        (++) One-pulse mode output
+    (#) Synchronization circuit to control the timer with external signals and to
+        interconnect several timers together.
+    (#) Break input to put the timer output signals in reset state or in a known state.
+    (#) Supports incremental (quadrature) encoder and hall-sensor circuitry for
+        positioning purposes
+
+            ##### How to use this driver #####
+  ==============================================================================
+    [..]
+     (#) Initialize the TIM low level resources by implementing the following functions
+         depending on the selected feature:
+           (++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit()
+
+     (#) Initialize the TIM low level resources :
+        (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
+        (##) TIM pins configuration
+            (+++) Enable the clock for the TIM GPIOs using the following function:
+              __HAL_RCC_GPIOx_CLK_ENABLE();
+            (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
+
+     (#) The external Clock can be configured, if needed (the default clock is the
+         internal clock from the APBx), using the following function:
+         HAL_TIM_ConfigClockSource, the clock configuration should be done before
+         any start function.
+
+     (#) Configure the TIM in the desired functioning mode using one of the
+         initialization function of this driver:
+          (++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutEvent(): to use the
+               Timer Hall Sensor Interface and the commutation event with the corresponding
+               Interrupt and DMA request if needed (Note that One Timer is used to interface
+               with the Hall sensor Interface and another Timer should be used to use
+               the commutation event).
+
+     (#) Activate the TIM peripheral using one of the start functions:
+           (++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(),
+                HAL_TIMEx_OCN_Start_IT()
+           (++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(),
+                HAL_TIMEx_PWMN_Start_IT()
+           (++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT()
+           (++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(),
+                HAL_TIMEx_HallSensor_Start_IT().
+
+  @endverbatim
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/** @addtogroup STM32WBxx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup TIMEx TIMEx
+  * @brief TIM Extended HAL module driver
+  * @{
+  */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Constants TIM Extended Private Constants
+  * @{
+  */
+/* Timeout for break input rearm */
+#define TIM_BREAKINPUT_REARM_TIMEOUT    5UL /* 5 milliseconds */
+/**
+  * @}
+  */
+/* End of private constants --------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup TIMEx_Private_Macros
+  * @{
+  */
+#if defined(STM32WB55xx) || defined(STM32WB5Mxx) || defined(STM32WB35xx)
+#define TIM_GET_OR_MASK(__INSTANCE__)                                                  \
+  (((__INSTANCE__) == TIM1) ? (TIM1_OR_ETR_ADC1_RMP | TIM1_OR_TI1_RMP) :               \
+   ((__INSTANCE__) == TIM2) ? (TIM2_OR_TI4_RMP | TIM2_OR_ETR_RMP | TIM2_OR_ITR1_RMP) : \
+   ((__INSTANCE__) == TIM16) ? TIM16_OR_TI1_RMP : TIM17_OR_TI1_RMP)
+#elif defined(STM32WB10xx)
+#define TIM_GET_OR_MASK(__INSTANCE__)                                    \
+  (((__INSTANCE__) == TIM1) ? (TIM1_OR_ETR_ADC1_RMP) : (TIM2_OR_ETR_RMP))
+#elif defined(STM32WB15xx) || defined(STM32WB1Mxx)
+#define TIM_GET_OR_MASK(__INSTANCE__)                                    \
+  (((__INSTANCE__) == TIM1) ? (TIM1_OR_ETR_ADC1_RMP | TIM1_OR_TI1_RMP) : \
+   (TIM2_OR_TI4_RMP | TIM2_OR_ETR_RMP))
+#else
+#define TIM_GET_OR_MASK(__INSTANCE__)                                    \
+  (((__INSTANCE__) == TIM1) ? (TIM1_OR_ETR_ADC1_RMP | TIM1_OR_TI1_RMP) : \
+   ((__INSTANCE__) == TIM2) ? TIM2_OR_ETR_RMP :                          \
+   ((__INSTANCE__) == TIM16) ? TIM16_OR_TI1_RMP : TIM17_OR_TI1_RMP)
+#endif
+/**
+  * @}
+  */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma);
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions
+  * @{
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions
+  * @brief    Timer Hall Sensor functions
+  *
+@verbatim
+  ==============================================================================
+                      ##### Timer Hall Sensor functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Initialize and configure TIM HAL Sensor.
+    (+) De-initialize TIM HAL Sensor.
+    (+) Start the Hall Sensor Interface.
+    (+) Stop the Hall Sensor Interface.
+    (+) Start the Hall Sensor Interface and enable interrupts.
+    (+) Stop the Hall Sensor Interface and disable interrupts.
+    (+) Start the Hall Sensor Interface and enable DMA transfers.
+    (+) Stop the Hall Sensor Interface and disable DMA transfers.
+
+@endverbatim
+  * @{
+  */
+/**
+  * @brief  Initializes the TIM Hall Sensor Interface and initialize the associated handle.
+  * @note   When the timer instance is initialized in Hall Sensor Interface mode,
+  *         timer channels 1 and channel 2 are reserved and cannot be used for
+  *         other purpose.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @param  sConfig TIM Hall Sensor configuration structure
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig)
+{
+  TIM_OC_InitTypeDef OC_Config;
+
+  /* Check the TIM handle allocation */
+  if (htim == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+  assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+  assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity));
+  assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+  assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+  assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+
+  if (htim->State == HAL_TIM_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+    /* Reset interrupt callbacks to legacy week callbacks */
+    TIM_ResetCallback(htim);
+
+    if (htim->HallSensor_MspInitCallback == NULL)
+    {
+      htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
+    }
+    /* Init the low level hardware : GPIO, CLOCK, NVIC */
+    htim->HallSensor_MspInitCallback(htim);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+    HAL_TIMEx_HallSensor_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+  }
+
+  /* Set the TIM state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Configure the Time base in the Encoder Mode */
+  TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+  /* Configure the Channel 1 as Input Channel to interface with the three Outputs of the  Hall sensor */
+  TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter);
+
+  /* Reset the IC1PSC Bits */
+  htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+  /* Set the IC1PSC value */
+  htim->Instance->CCMR1 |= sConfig->IC1Prescaler;
+
+  /* Enable the Hall sensor interface (XOR function of the three inputs) */
+  htim->Instance->CR2 |= TIM_CR2_TI1S;
+
+  /* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */
+  htim->Instance->SMCR &= ~TIM_SMCR_TS;
+  htim->Instance->SMCR |= TIM_TS_TI1F_ED;
+
+  /* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */
+  htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+  htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
+
+  /* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/
+  OC_Config.OCFastMode = TIM_OCFAST_DISABLE;
+  OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET;
+  OC_Config.OCMode = TIM_OCMODE_PWM2;
+  OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+  OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+  OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH;
+  OC_Config.Pulse = sConfig->Commutation_Delay;
+
+  TIM_OC2_SetConfig(htim->Instance, &OC_Config);
+
+  /* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2
+    register to 101 */
+  htim->Instance->CR2 &= ~TIM_CR2_MMS;
+  htim->Instance->CR2 |= TIM_TRGO_OC2REF;
+
+  /* Initialize the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+  /* Initialize the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Initialize the TIM state*/
+  htim->State = HAL_TIM_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  DeInitializes the TIM Hall Sensor interface
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Disable the TIM Peripheral Clock */
+  __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  if (htim->HallSensor_MspDeInitCallback == NULL)
+  {
+    htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+  }
+  /* DeInit the low level hardware */
+  htim->HallSensor_MspDeInitCallback(htim);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+  HAL_TIMEx_HallSensor_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  /* Change the DMA burst operation state */
+  htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+  /* Change the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+  /* Change TIM state */
+  htim->State = HAL_TIM_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes the TIM Hall Sensor MSP.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  DeInitializes TIM Hall Sensor MSP.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Starts the TIM Hall Sensor Interface.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Hall sensor Interface.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channels 1, 2 and 3
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Hall Sensor Interface in interrupt mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the capture compare Interrupts 1 event */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+  /* Enable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Hall Sensor Interface in interrupt mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+  /* Disable the capture compare Interrupts event */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Hall Sensor Interface in DMA mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @param  pData The destination Buffer address.
+  * @param  Length The length of data to be transferred from TIM peripheral to memory.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length)
+{
+  uint32_t tmpsmcr;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Set the TIM channel state */
+  if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+      || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
+  {
+    return HAL_BUSY;
+  }
+  else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+           && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  /* Enable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+  /* Set the DMA Input Capture 1 Callbacks */
+  htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+  htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+  /* Set the DMA error callback */
+  htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+  /* Enable the DMA channel for Capture 1*/
+  if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length) != HAL_OK)
+  {
+    /* Return error status */
+    return HAL_ERROR;
+  }
+  /* Enable the capture compare 1 Interrupt */
+  __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Hall Sensor Interface in DMA mode.
+  * @param  htim TIM Hall Sensor Interface handle
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+  /* Disable the Input Capture channel 1
+  (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+  TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+  TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+
+  /* Disable the capture compare Interrupts 1 event */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+
+  (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM channel state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions
+  *  @brief   Timer Complementary Output Compare functions
+  *
+@verbatim
+  ==============================================================================
+              ##### Timer Complementary Output Compare functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Start the Complementary Output Compare/PWM.
+    (+) Stop the Complementary Output Compare/PWM.
+    (+) Start the Complementary Output Compare/PWM and enable interrupts.
+    (+) Stop the Complementary Output Compare/PWM and disable interrupts.
+    (+) Start the Complementary Output Compare/PWM and enable DMA transfers.
+    (+) Stop the Complementary Output Compare/PWM and disable DMA transfers.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation on the complementary
+  *         output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the Capture compare channel N */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation on the complementary
+  *         output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the Capture compare channel N */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in interrupt mode
+  *         on the complementary output.
+  * @param  htim TIM OC handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Output Compare interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Output Compare interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Output Compare interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the TIM Break interrupt */
+    __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+    /* Enable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in interrupt mode
+  *         on the complementary output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpccer;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Output Compare interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Output Compare interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Output Compare interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the TIM Break interrupt (only if no more channel is active) */
+    tmpccer = htim->Instance->CCER;
+    if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == (uint32_t)RESET)
+    {
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+    }
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM Output Compare signal generation in DMA mode
+  *         on the complementary output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                          uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Compare DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Compare DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Output Compare DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM Output Compare signal generation in DMA mode
+  *         on the complementary output.
+  * @param  htim TIM Output Compare handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Output Compare DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Output Compare DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Output Compare DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the Capture compare channel N */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
+  * @brief    Timer Complementary PWM functions
+  *
+@verbatim
+  ==============================================================================
+                 ##### Timer Complementary PWM functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Start the Complementary PWM.
+    (+) Stop the Complementary PWM.
+    (+) Start the Complementary PWM and enable interrupts.
+    (+) Stop the Complementary PWM and disable interrupts.
+    (+) Start the Complementary PWM and enable DMA transfers.
+    (+) Stop the Complementary PWM and disable DMA transfers.
+    (+) Start the Complementary Input Capture measurement.
+    (+) Stop the Complementary Input Capture.
+    (+) Start the Complementary Input Capture and enable interrupts.
+    (+) Stop the Complementary Input Capture and disable interrupts.
+    (+) Start the Complementary Input Capture and enable DMA transfers.
+    (+) Stop the Complementary Input Capture and disable DMA transfers.
+    (+) Start the Complementary One Pulse generation.
+    (+) Stop the Complementary One Pulse.
+    (+) Start the Complementary One Pulse and enable interrupts.
+    (+) Stop the Complementary One Pulse and disable interrupts.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Starts the PWM signal generation on the complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the complementary PWM output  */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+  else
+  {
+    __HAL_TIM_ENABLE(htim);
+  }
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the PWM signal generation on the complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Disable the complementary PWM output  */
+  TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the PWM signal generation in interrupt mode on the
+  *         complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Check the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM complementary channel state */
+  TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Enable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Enable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Enable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the TIM Break interrupt */
+    __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+    /* Enable the complementary PWM output  */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the PWM signal generation in interrupt mode on the
+  *         complementary output.
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpccer;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 interrupt */
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the complementary PWM output  */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the TIM Break interrupt (only if no more channel is active) */
+    tmpccer = htim->Instance->CCER;
+    if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == (uint32_t)RESET)
+    {
+      __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+    }
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Starts the TIM PWM signal generation in DMA mode on the
+  *         complementary output
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be enabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @param  pData The source Buffer address.
+  * @param  Length The length of data to be transferred from memory to TIM peripheral
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+                                           uint16_t Length)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  /* Set the TIM complementary channel state */
+  if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+  {
+    return HAL_BUSY;
+  }
+  else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+  {
+    if ((pData == NULL) || (Length == 0U))
+    {
+      return HAL_ERROR;
+    }
+    else
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+    }
+  }
+  else
+  {
+    return HAL_ERROR;
+  }
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Set the DMA compare callbacks */
+      htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+      htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+      /* Set the DMA error callback */
+      htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+      /* Enable the DMA channel */
+      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+                           Length) != HAL_OK)
+      {
+        /* Return error status */
+        return HAL_ERROR;
+      }
+      /* Enable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Enable the complementary PWM output  */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+    /* Enable the Main Output */
+    __HAL_TIM_MOE_ENABLE(htim);
+
+    /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+    if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+    {
+      tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+      if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+      {
+        __HAL_TIM_ENABLE(htim);
+      }
+    }
+    else
+    {
+      __HAL_TIM_ENABLE(htim);
+    }
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @brief  Stops the TIM PWM signal generation in DMA mode on the complementary
+  *         output
+  * @param  htim TIM handle
+  * @param  Channel TIM Channel to be disabled
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+  switch (Channel)
+  {
+    case TIM_CHANNEL_1:
+    {
+      /* Disable the TIM Capture/Compare 1 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+      break;
+    }
+
+    case TIM_CHANNEL_2:
+    {
+      /* Disable the TIM Capture/Compare 2 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+      break;
+    }
+
+    case TIM_CHANNEL_3:
+    {
+      /* Disable the TIM Capture/Compare 3 DMA request */
+      __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+      (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+      break;
+    }
+
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  if (status == HAL_OK)
+  {
+    /* Disable the complementary PWM output */
+    TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+    /* Disable the Main Output */
+    __HAL_TIM_MOE_DISABLE(htim);
+
+    /* Disable the Peripheral */
+    __HAL_TIM_DISABLE(htim);
+
+    /* Set the TIM complementary channel state */
+    TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+  }
+
+  /* Return function status */
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
+  * @brief    Timer Complementary One Pulse functions
+  *
+@verbatim
+  ==============================================================================
+                ##### Timer Complementary One Pulse functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+    (+) Start the Complementary One Pulse generation.
+    (+) Stop the Complementary One Pulse.
+    (+) Start the Complementary One Pulse and enable interrupts.
+    (+) Stop the Complementary One Pulse and disable interrupts.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation on the complementary
+  *         output.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to enable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation on the complementary
+  *         output.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to disable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Disable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM  channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Starts the TIM One Pulse signal generation in interrupt mode on the
+  *         complementary channel.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to enable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+  HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+  HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Check the TIM channels state */
+  if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+      || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Set the TIM channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+  /* Enable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+  /* Enable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+  /* Enable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
+
+  /* Enable the Main Output */
+  __HAL_TIM_MOE_ENABLE(htim);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stops the TIM One Pulse signal generation in interrupt mode on the
+  *         complementary channel.
+  * @note OutputChannel must match the pulse output channel chosen when calling
+  *       @ref HAL_TIM_OnePulse_ConfigChannel().
+  * @param  htim TIM One Pulse handle
+  * @param  OutputChannel pulse output channel to disable
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
+  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+  uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+  /* Disable the TIM Capture/Compare 1 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+  /* Disable the TIM Capture/Compare 2 interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+  /* Disable the complementary One Pulse output channel and the Input Capture channel */
+  TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+  TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
+
+  /* Disable the Main Output */
+  __HAL_TIM_MOE_DISABLE(htim);
+
+  /* Disable the Peripheral */
+  __HAL_TIM_DISABLE(htim);
+
+  /* Set the TIM  channels state */
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+  /* Return function status */
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
+  * @brief    Peripheral Control functions
+  *
+@verbatim
+  ==============================================================================
+                    ##### Peripheral Control functions #####
+  ==============================================================================
+  [..]
+    This section provides functions allowing to:
+      (+) Configure the commutation event in case of use of the Hall sensor interface.
+      (+) Configure Output channels for OC and PWM mode.
+
+      (+) Configure Complementary channels, break features and dead time.
+      (+) Configure Master synchronization.
+      (+) Configure timer remapping capabilities.
+      (+) Enable or disable channel grouping.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Configure the TIM commutation event sequence.
+  * @note  This function is mandatory to use the commutation event in order to
+  *        update the configuration at each commutation detection on the TRGI input of the Timer,
+  *        the typical use of this feature is with the use of another Timer(interface Timer)
+  *        configured in Hall sensor interface, this interface Timer will generate the
+  *        commutation at its TRGO output (connected to Timer used in this function) each time
+  *        the TI1 of the Interface Timer detect a commutation at its input TI1.
+  * @param  htim TIM handle
+  * @param  InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal trigger 0 selected
+  *            @arg TIM_TS_ITR1: Internal trigger 1 selected
+  *            @arg TIM_TS_ITR2: Internal trigger 2 selected
+  *            @arg TIM_TS_ITR3: Internal trigger 3 selected
+  *            @arg TIM_TS_NONE: No trigger is needed
+  * @param  CommutationSource the Commutation Event source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+  *            @arg TIM_COMMUTATION_SOFTWARE:  Commutation source is set by software using the COMG bit
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                              uint32_t  CommutationSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+      (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
+  {
+    /* Select the Input trigger */
+    htim->Instance->SMCR &= ~TIM_SMCR_TS;
+    htim->Instance->SMCR |= InputTrigger;
+  }
+
+  /* Select the Capture Compare preload feature */
+  htim->Instance->CR2 |= TIM_CR2_CCPC;
+  /* Select the Commutation event source */
+  htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+  htim->Instance->CR2 |= CommutationSource;
+
+  /* Disable Commutation Interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
+
+  /* Disable Commutation DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configure the TIM commutation event sequence with interrupt.
+  * @note  This function is mandatory to use the commutation event in order to
+  *        update the configuration at each commutation detection on the TRGI input of the Timer,
+  *        the typical use of this feature is with the use of another Timer(interface Timer)
+  *        configured in Hall sensor interface, this interface Timer will generate the
+  *        commutation at its TRGO output (connected to Timer used in this function) each time
+  *        the TI1 of the Interface Timer detect a commutation at its input TI1.
+  * @param  htim TIM handle
+  * @param  InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal trigger 0 selected
+  *            @arg TIM_TS_ITR1: Internal trigger 1 selected
+  *            @arg TIM_TS_ITR2: Internal trigger 2 selected
+  *            @arg TIM_TS_ITR3: Internal trigger 3 selected
+  *            @arg TIM_TS_NONE: No trigger is needed
+  * @param  CommutationSource the Commutation Event source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+  *            @arg TIM_COMMUTATION_SOFTWARE:  Commutation source is set by software using the COMG bit
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                                 uint32_t  CommutationSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+      (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
+  {
+    /* Select the Input trigger */
+    htim->Instance->SMCR &= ~TIM_SMCR_TS;
+    htim->Instance->SMCR |= InputTrigger;
+  }
+
+  /* Select the Capture Compare preload feature */
+  htim->Instance->CR2 |= TIM_CR2_CCPC;
+  /* Select the Commutation event source */
+  htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+  htim->Instance->CR2 |= CommutationSource;
+
+  /* Disable Commutation DMA request */
+  __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
+
+  /* Enable the Commutation Interrupt */
+  __HAL_TIM_ENABLE_IT(htim, TIM_IT_COM);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configure the TIM commutation event sequence with DMA.
+  * @note  This function is mandatory to use the commutation event in order to
+  *        update the configuration at each commutation detection on the TRGI input of the Timer,
+  *        the typical use of this feature is with the use of another Timer(interface Timer)
+  *        configured in Hall sensor interface, this interface Timer will generate the
+  *        commutation at its TRGO output (connected to Timer used in this function) each time
+  *        the TI1 of the Interface Timer detect a commutation at its input TI1.
+  * @note  The user should configure the DMA in his own software, in This function only the COMDE bit is set
+  * @param  htim TIM handle
+  * @param  InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+  *          This parameter can be one of the following values:
+  *            @arg TIM_TS_ITR0: Internal trigger 0 selected
+  *            @arg TIM_TS_ITR1: Internal trigger 1 selected
+  *            @arg TIM_TS_ITR2: Internal trigger 2 selected
+  *            @arg TIM_TS_ITR3: Internal trigger 3 selected
+  *            @arg TIM_TS_NONE: No trigger is needed
+  * @param  CommutationSource the Commutation Event source
+  *          This parameter can be one of the following values:
+  *            @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+  *            @arg TIM_COMMUTATION_SOFTWARE:  Commutation source is set by software using the COMG bit
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t  InputTrigger,
+                                                  uint32_t  CommutationSource)
+{
+  /* Check the parameters */
+  assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+  __HAL_LOCK(htim);
+
+  if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+      (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
+  {
+    /* Select the Input trigger */
+    htim->Instance->SMCR &= ~TIM_SMCR_TS;
+    htim->Instance->SMCR |= InputTrigger;
+  }
+
+  /* Select the Capture Compare preload feature */
+  htim->Instance->CR2 |= TIM_CR2_CCPC;
+  /* Select the Commutation event source */
+  htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+  htim->Instance->CR2 |= CommutationSource;
+
+  /* Enable the Commutation DMA Request */
+  /* Set the DMA Commutation Callback */
+  htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+  htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
+  /* Set the DMA error callback */
+  htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError;
+
+  /* Disable Commutation Interrupt */
+  __HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
+
+  /* Enable the Commutation DMA Request */
+  __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the TIM in master mode.
+  * @param  htim TIM handle.
+  * @param  sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that
+  *         contains the selected trigger output (TRGO) and the Master/Slave
+  *         mode.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
+                                                        const TIM_MasterConfigTypeDef *sMasterConfig)
+{
+  uint32_t tmpcr2;
+  uint32_t tmpsmcr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_MASTER_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
+  assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
+
+  /* Check input state */
+  __HAL_LOCK(htim);
+
+  /* Change the handler state */
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Get the TIMx CR2 register value */
+  tmpcr2 = htim->Instance->CR2;
+
+  /* Get the TIMx SMCR register value */
+  tmpsmcr = htim->Instance->SMCR;
+
+  /* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */
+  if (IS_TIM_TRGO2_INSTANCE(htim->Instance))
+  {
+    /* Check the parameters */
+    assert_param(IS_TIM_TRGO2_SOURCE(sMasterConfig->MasterOutputTrigger2));
+
+    /* Clear the MMS2 bits */
+    tmpcr2 &= ~TIM_CR2_MMS2;
+    /* Select the TRGO2 source*/
+    tmpcr2 |= sMasterConfig->MasterOutputTrigger2;
+  }
+
+  /* Reset the MMS Bits */
+  tmpcr2 &= ~TIM_CR2_MMS;
+  /* Select the TRGO source */
+  tmpcr2 |=  sMasterConfig->MasterOutputTrigger;
+
+  /* Update TIMx CR2 */
+  htim->Instance->CR2 = tmpcr2;
+
+  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+  {
+    /* Reset the MSM Bit */
+    tmpsmcr &= ~TIM_SMCR_MSM;
+    /* Set master mode */
+    tmpsmcr |= sMasterConfig->MasterSlaveMode;
+
+    /* Update TIMx SMCR */
+    htim->Instance->SMCR = tmpsmcr;
+  }
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the Break feature, dead time, Lock level, OSSI/OSSR State
+  *         and the AOE(automatic output enable).
+  * @param  htim TIM handle
+  * @param  sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that
+  *         contains the BDTR Register configuration  information for the TIM peripheral.
+  * @note   Interrupts can be generated when an active level is detected on the
+  *         break input, the break 2 input or the system break input. Break
+  *         interrupt can be enabled by calling the @ref __HAL_TIM_ENABLE_IT macro.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
+                                                const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig)
+{
+  /* Keep this variable initialized to 0 as it is used to configure BDTR register */
+  uint32_t tmpbdtr = 0U;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode));
+  assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode));
+  assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel));
+  assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime));
+  assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState));
+  assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity));
+  assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->BreakFilter));
+  assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput));
+
+  /* Check input state */
+  __HAL_LOCK(htim);
+
+  /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
+     the OSSI State, the dead time value and the Automatic Output Enable Bit */
+
+  /* Set the BDTR bits */
+  MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput);
+  MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (sBreakDeadTimeConfig->BreakFilter << TIM_BDTR_BKF_Pos));
+
+  if (IS_TIM_ADVANCED_INSTANCE(htim->Instance))
+  {
+    /* Check the parameters */
+    assert_param(IS_TIM_BREAK_AFMODE(sBreakDeadTimeConfig->BreakAFMode));
+
+    /* Set BREAK AF mode */
+    MODIFY_REG(tmpbdtr, TIM_BDTR_BKBID, sBreakDeadTimeConfig->BreakAFMode);
+  }
+
+  if (IS_TIM_BKIN2_INSTANCE(htim->Instance))
+  {
+    /* Check the parameters */
+    assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State));
+    assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity));
+    assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter));
+
+    /* Set the BREAK2 input related BDTR bits */
+    MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (sBreakDeadTimeConfig->Break2Filter << TIM_BDTR_BK2F_Pos));
+    MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, sBreakDeadTimeConfig->Break2State);
+    MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, sBreakDeadTimeConfig->Break2Polarity);
+
+    if (IS_TIM_ADVANCED_INSTANCE(htim->Instance))
+    {
+      /* Check the parameters */
+      assert_param(IS_TIM_BREAK2_AFMODE(sBreakDeadTimeConfig->Break2AFMode));
+
+      /* Set BREAK2 AF mode */
+      MODIFY_REG(tmpbdtr, TIM_BDTR_BK2BID, sBreakDeadTimeConfig->Break2AFMode);
+    }
+  }
+
+  /* Set TIMx_BDTR */
+  htim->Instance->BDTR = tmpbdtr;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Configures the break input source.
+  * @param  htim TIM handle.
+  * @param  BreakInput Break input to configure
+  *          This parameter can be one of the following values:
+  *            @arg TIM_BREAKINPUT_BRK: Timer break input
+  *            @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
+  * @param  sBreakInputConfig Break input source configuration
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim,
+                                             uint32_t BreakInput,
+                                             const TIMEx_BreakInputConfigTypeDef *sBreakInputConfig)
+
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmporx;
+  uint32_t bkin_enable_mask;
+  uint32_t bkin_polarity_mask;
+  uint32_t bkin_enable_bitpos;
+  uint32_t bkin_polarity_bitpos;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_BREAKINPUT(BreakInput));
+  assert_param(IS_TIM_BREAKINPUTSOURCE(sBreakInputConfig->Source));
+  assert_param(IS_TIM_BREAKINPUTSOURCE_STATE(sBreakInputConfig->Enable));
+  assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity));
+
+  /* Check input state */
+  __HAL_LOCK(htim);
+
+  switch (sBreakInputConfig->Source)
+  {
+    case TIM_BREAKINPUTSOURCE_BKIN:
+    {
+      bkin_enable_mask = TIM1_AF1_BKINE;
+      bkin_enable_bitpos = TIM1_AF1_BKINE_Pos;
+      bkin_polarity_mask = TIM1_AF1_BKINP;
+      bkin_polarity_bitpos = TIM1_AF1_BKINP_Pos;
+      break;
+    }
+#if defined(COMP1) && defined(COMP2)
+    case TIM_BREAKINPUTSOURCE_COMP1:
+    {
+      bkin_enable_mask = TIM1_AF1_BKCMP1E;
+      bkin_enable_bitpos = TIM1_AF1_BKCMP1E_Pos;
+      bkin_polarity_mask = TIM1_AF1_BKCMP1P;
+      bkin_polarity_bitpos = TIM1_AF1_BKCMP1P_Pos;
+      break;
+    }
+    case TIM_BREAKINPUTSOURCE_COMP2:
+    {
+      bkin_enable_mask = TIM1_AF1_BKCMP2E;
+      bkin_enable_bitpos = TIM1_AF1_BKCMP2E_Pos;
+      bkin_polarity_mask = TIM1_AF1_BKCMP2P;
+      bkin_polarity_bitpos = TIM1_AF1_BKCMP2P_Pos;
+      break;
+    }
+#endif /* COMP1 && COMP2 */
+
+    default:
+    {
+      bkin_enable_mask = 0U;
+      bkin_polarity_mask = 0U;
+      bkin_enable_bitpos = 0U;
+      bkin_polarity_bitpos = 0U;
+      break;
+    }
+  }
+
+  switch (BreakInput)
+  {
+    case TIM_BREAKINPUT_BRK:
+    {
+      /* Get the TIMx_AF1 register value */
+      tmporx = htim->Instance->AF1;
+
+      /* Enable the break input */
+      tmporx &= ~bkin_enable_mask;
+      tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
+
+      /* Set the break input polarity */
+      tmporx &= ~bkin_polarity_mask;
+      tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
+
+      /* Set TIMx_AF1 */
+      htim->Instance->AF1 = tmporx;
+      break;
+    }
+    case TIM_BREAKINPUT_BRK2:
+    {
+      /* Get the TIMx_AF2 register value */
+      tmporx = htim->Instance->AF2;
+
+      /* Enable the break input */
+      tmporx &= ~bkin_enable_mask;
+      tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
+
+      /* Set the break input polarity */
+      tmporx &= ~bkin_polarity_mask;
+      tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
+
+      /* Set TIMx_AF2 */
+      htim->Instance->AF2 = tmporx;
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  __HAL_UNLOCK(htim);
+
+  return status;
+}
+
+/**
+  * @brief  Configures the TIMx Remapping input capabilities.
+  * @param  htim TIM handle.
+  * @param  Remap specifies the TIM remapping source.
+  *     For TIM1, the parameter is a combination of 2 fields (field1 | field2):
+  *
+  *       field1 can have the following values:
+  *            @arg TIM_TIM1_ETR_ADC1_GPIO:           TIM1_ETR is connected to I/O
+  *            @arg TIM_TIM1_ETR_ADC1_AWD1:           TIM1_ETR is connected to ADC1 AWD1
+  *            @arg TIM_TIM1_ETR_ADC1_AWD2:           TIM1_ETR is connected to ADC1 AWD2 (*)
+  *            @arg TIM_TIM1_ETR_ADC1_AWD3:           TIM1_ETR is connected to ADC1 AWD3 (*)
+  *            @arg TIM_TIM1_ETR_COMP1:               TIM1_ETR is connected to COMP1 output (*)
+  *            @arg TIM_TIM1_ETR_COMP2:               TIM1_ETR is connected to COMP2 output (*)
+  *       field2 can have the following values:
+  *            @arg TIM_TIM1_TI1_GPIO:                TIM1 TI1 is connected to I/O
+  *            @arg TIM_TIM1_TI1_COMP1:               TIM1 TI1 is connected to COMP1 output (*)
+  *
+  *        For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3):
+  *
+  *       field1 can have the following values:
+  *            @arg TIM_TIM2_ITR1_NONE:               No internal trigger on TIM2_ITR1
+  *            @arg TIM_TIM2_ITR1_USB:                TIM2_ITR1 is connected to USB SOF (*)
+  *
+  *       field2 can have the following values:
+  *            @arg TIM_TIM2_ETR_GPIO:                TIM2_ETR is connected to I/O
+  *            @arg TIM_TIM2_ETR_LSE:                 TIM2_ETR is connected to LSE
+  *            @arg TIM_TIM2_ETR_COMP1:               TIM2_ETR is connected to COMP1 output (*)
+  *            @arg TIM_TIM2_ETR_COMP2:               TIM2_ETR is connected to COMP2 output (*)
+  *
+  *       field3 can have the following values:
+  *            @arg TIM_TIM2_TI4_GPIO:                TIM2 TI4 is connected to I/O
+  *            @arg TIM_TIM2_TI4_COMP1:               TIM2 TI4 is connected to COMP1 output (*)
+  *            @arg TIM_TIM2_TI4_COMP2:               TIM2 TI4 is connected to COMP2 output (*)
+  *            @arg TIM_TIM2_TI4_COMP1_COMP2:         TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output (*)
+  *
+  *     For TIM16, the parameter can have the following values:
+  *            @arg TIM_TIM16_TI1_GPIO:              TIM16 TI1 is connected to I/O
+  *            @arg TIM_TIM16_TI1_LSI:               TIM16 TI1 is connected to LSI
+  *            @arg TIM_TIM16_TI1_LSE:               TIM16 TI1 is connected to LSE
+  *            @arg TIM_TIM16_TI1_RTC:               TIM16 TI1 is connected to RTC wakeup interrupt
+  *
+  *     For TIM17, the parameter can have the following values:
+  *            @arg TIM_TIM17_TI1_GPIO:              TIM17 TI1 is connected to I/O
+  *            @arg TIM_TIM17_TI1_MSI:               TIM17 TI1 is connected to MSI  (constraint: MSI clock < 1/4 TIM APB clock)
+  *            @arg TIM_TIM17_TI1_HSE:               TIM17 TI1 is connected to HSE div 32
+  *            @arg TIM_TIM17_TI1_MCO:               TIM17 TI1 is connected to MCO
+  *
+  *         (*)  Value not defined in all devices.
+  *
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
+{
+  uint32_t tmpor;
+  uint32_t tmpaf1;
+
+  /* Check parameters */
+  assert_param(IS_TIM_REMAP(htim->Instance, Remap));
+
+  __HAL_LOCK(htim);
+
+  /* Read TIMx_OR */
+  tmpor = READ_REG(htim->Instance->OR);
+
+  /* Read TIMx_AF1 */
+  tmpaf1 = READ_REG(htim->Instance->AF1);
+
+  /* Set ETR_SEL bit field (if required) */
+  if (IS_TIM_ETRSEL_INSTANCE(htim->Instance))
+  {
+    if ((Remap & TIM1_AF1_ETRSEL) != (uint32_t)RESET)
+    {
+      /* COMP1 output or COMP2 output connected to ETR input */
+      MODIFY_REG(tmpaf1, TIM1_AF1_ETRSEL, (Remap & TIM1_AF1_ETRSEL));
+    }
+    else
+    {
+      /* ETR legacy mode */
+      MODIFY_REG(tmpaf1, TIM1_AF1_ETRSEL, 0U);
+    }
+
+    /* Set TIMx_AF1 */
+    WRITE_REG(htim->Instance->AF1, tmpaf1);
+  }
+
+  /* Set other remapping capabilities */
+  MODIFY_REG(tmpor, TIM_GET_OR_MASK(htim->Instance), (Remap & (~TIM1_AF1_ETRSEL)));
+
+  /* Set TIMx_OR */
+  WRITE_REG(htim->Instance->OR, tmpor);
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Group channel 5 and channel 1, 2 or 3
+  * @param  htim TIM handle.
+  * @param  Channels specifies the reference signal(s) the OC5REF is combined with.
+  *         This parameter can be any combination of the following values:
+  *         TIM_GROUPCH5_NONE: No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC
+  *         TIM_GROUPCH5_OC1REFC: OC1REFC is the logical AND of OC1REFC and OC5REF
+  *         TIM_GROUPCH5_OC2REFC: OC2REFC is the logical AND of OC2REFC and OC5REF
+  *         TIM_GROUPCH5_OC3REFC: OC3REFC is the logical AND of OC3REFC and OC5REF
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels)
+{
+  /* Check parameters */
+  assert_param(IS_TIM_COMBINED3PHASEPWM_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_GROUPCH5(Channels));
+
+  /* Process Locked */
+  __HAL_LOCK(htim);
+
+  htim->State = HAL_TIM_STATE_BUSY;
+
+  /* Clear GC5Cx bit fields */
+  htim->Instance->CCR5 &= ~(TIM_CCR5_GC5C3 | TIM_CCR5_GC5C2 | TIM_CCR5_GC5C1);
+
+  /* Set GC5Cx bit fields */
+  htim->Instance->CCR5 |= Channels;
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+  __HAL_UNLOCK(htim);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Disarm the designated break input (when it operates in bidirectional mode).
+  * @param  htim TIM handle.
+  * @param  BreakInput Break input to disarm
+  *          This parameter can be one of the following values:
+  *            @arg TIM_BREAKINPUT_BRK: Timer break input
+  *            @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
+  * @note  The break input can be disarmed only when it is configured in
+  *        bidirectional mode and when when MOE is reset.
+  * @note  Purpose is to be able to have the input voltage back to high-state,
+  *        whatever the time constant on the output .
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_DisarmBreakInput(TIM_HandleTypeDef *htim, uint32_t BreakInput)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tmpbdtr;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ADVANCED_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_BREAKINPUT(BreakInput));
+
+  switch (BreakInput)
+  {
+    case TIM_BREAKINPUT_BRK:
+    {
+      /* Check initial conditions */
+      tmpbdtr = READ_REG(htim->Instance->BDTR);
+      if ((READ_BIT(tmpbdtr, TIM_BDTR_BKBID) == TIM_BDTR_BKBID) &&
+          (READ_BIT(tmpbdtr, TIM_BDTR_MOE) == 0U))
+      {
+        /* Break input BRK is disarmed */
+        SET_BIT(htim->Instance->BDTR, TIM_BDTR_BKDSRM);
+      }
+      break;
+    }
+
+    case TIM_BREAKINPUT_BRK2:
+    {
+      /* Check initial conditions */
+      tmpbdtr = READ_REG(htim->Instance->BDTR);
+      if ((READ_BIT(tmpbdtr, TIM_BDTR_BK2BID) == TIM_BDTR_BK2BID) &&
+          (READ_BIT(tmpbdtr, TIM_BDTR_MOE) == 0U))
+      {
+        /* Break input BRK is disarmed */
+        SET_BIT(htim->Instance->BDTR, TIM_BDTR_BK2DSRM);
+      }
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Arm the designated break input (when it operates in bidirectional mode).
+  * @param  htim TIM handle.
+  * @param  BreakInput Break input to arm
+  *          This parameter can be one of the following values:
+  *            @arg TIM_BREAKINPUT_BRK: Timer break input
+  *            @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
+  * @note  Arming is possible at anytime, even if fault is present.
+  * @note  Break input is automatically armed as soon as MOE bit is set.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_TIMEx_ReArmBreakInput(TIM_HandleTypeDef *htim, uint32_t BreakInput)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint32_t tickstart;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_ADVANCED_INSTANCE(htim->Instance));
+  assert_param(IS_TIM_BREAKINPUT(BreakInput));
+
+  switch (BreakInput)
+  {
+    case TIM_BREAKINPUT_BRK:
+    {
+      /* Check initial conditions */
+      if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BKBID) == TIM_BDTR_BKBID)
+      {
+        /* Break input BRK is re-armed automatically by hardware. Poll to check whether fault condition disappeared */
+        /* Init tickstart for timeout management */
+        tickstart = HAL_GetTick();
+        while (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BKDSRM) != 0UL)
+        {
+          if ((HAL_GetTick() - tickstart) > TIM_BREAKINPUT_REARM_TIMEOUT)
+          {
+            /* New check to avoid false timeout detection in case of preemption */
+            if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BKDSRM) != 0UL)
+            {
+              return HAL_TIMEOUT;
+            }
+          }
+        }
+      }
+      break;
+    }
+
+    case TIM_BREAKINPUT_BRK2:
+    {
+      /* Check initial conditions */
+      if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BK2BID) == TIM_BDTR_BK2BID)
+      {
+        /* Break input BRK2 is re-armed automatically by hardware. Poll to check whether fault condition disappeared */
+        /* Init tickstart for timeout management */
+        tickstart = HAL_GetTick();
+        while (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BK2DSRM) != 0UL)
+        {
+          if ((HAL_GetTick() - tickstart) > TIM_BREAKINPUT_REARM_TIMEOUT)
+          {
+            /* New check to avoid false timeout detection in case of preemption */
+            if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BK2DSRM) != 0UL)
+            {
+              return HAL_TIMEOUT;
+            }
+          }
+        }
+      }
+      break;
+    }
+    default:
+      status = HAL_ERROR;
+      break;
+  }
+
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
+  * @brief    Extended Callbacks functions
+  *
+@verbatim
+  ==============================================================================
+                    ##### Extended Callbacks functions #####
+  ==============================================================================
+  [..]
+    This section provides Extended TIM callback functions:
+    (+) Timer Commutation callback
+    (+) Timer Break callback
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Hall commutation changed callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_CommutCallback could be implemented in the user file
+   */
+}
+/**
+  * @brief  Hall commutation changed half complete callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_CommutHalfCpltCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Hall Break detection callback in non-blocking mode
+  * @param  htim TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_TIMEx_BreakCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Hall Break2 detection callback in non blocking mode
+  * @param  htim: TIM handle
+  * @retval None
+  */
+__weak void HAL_TIMEx_Break2Callback(TIM_HandleTypeDef *htim)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(htim);
+
+  /* NOTE : This function Should not be modified, when the callback is needed,
+            the HAL_TIMEx_Break2Callback could be implemented in the user file
+   */
+}
+/**
+  * @}
+  */
+
+/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
+  * @brief    Extended Peripheral State functions
+  *
+@verbatim
+  ==============================================================================
+                ##### Extended Peripheral State functions #####
+  ==============================================================================
+  [..]
+    This subsection permits to get in run-time the status of the peripheral
+    and the data flow.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the TIM Hall Sensor interface handle state.
+  * @param  htim TIM Hall Sensor handle
+  * @retval HAL state
+  */
+HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim)
+{
+  return htim->State;
+}
+
+/**
+  * @brief  Return actual state of the TIM complementary channel.
+  * @param  htim TIM handle
+  * @param  ChannelN TIM Complementary channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  * @retval TIM Complementary channel state
+  */
+HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim,  uint32_t ChannelN)
+{
+  HAL_TIM_ChannelStateTypeDef channel_state;
+
+  /* Check the parameters */
+  assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, ChannelN));
+
+  channel_state = TIM_CHANNEL_N_STATE_GET(htim, ChannelN);
+
+  return channel_state;
+}
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Functions TIM Extended Private Functions
+  * @{
+  */
+
+/**
+  * @brief  TIM DMA Commutation callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->CommutationCallback(htim);
+#else
+  HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  TIM DMA Commutation half complete callback.
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  /* Change the htim state */
+  htim->State = HAL_TIM_STATE_READY;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->CommutationHalfCpltCallback(htim);
+#else
+  HAL_TIMEx_CommutHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+
+/**
+  * @brief  TIM DMA Delay Pulse complete callback (complementary channel).
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+    if (hdma->Init.Mode == DMA_NORMAL)
+    {
+      TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+    }
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->PWM_PulseFinishedCallback(htim);
+#else
+  HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  TIM DMA error callback (complementary channel)
+  * @param  hdma pointer to DMA handle.
+  * @retval None
+  */
+static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma)
+{
+  TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+  if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+  {
+    htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+    TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+  }
+  else
+  {
+    /* nothing to do */
+  }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+  htim->ErrorCallback(htim);
+#else
+  HAL_TIM_ErrorCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+  htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+  * @brief  Enables or disables the TIM Capture Compare Channel xN.
+  * @param  TIMx to select the TIM peripheral
+  * @param  Channel specifies the TIM Channel
+  *          This parameter can be one of the following values:
+  *            @arg TIM_CHANNEL_1: TIM Channel 1
+  *            @arg TIM_CHANNEL_2: TIM Channel 2
+  *            @arg TIM_CHANNEL_3: TIM Channel 3
+  * @param  ChannelNState specifies the TIM Channel CCxNE bit new state.
+  *          This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable.
+  * @retval None
+  */
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState)
+{
+  uint32_t tmp;
+
+  tmp = TIM_CCER_CC1NE << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
+
+  /* Reset the CCxNE Bit */
+  TIMx->CCER &=  ~tmp;
+
+  /* Set or reset the CCxNE Bit */
+  TIMx->CCER |= (uint32_t)(ChannelNState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
+}
+/**
+  * @}
+  */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */

BIN
photos/freq.jpg


BIN
photos/rigol.jpg


BIN
photos/sig.jpg


BIN
photos/volt.jpg


+ 30 - 0
scenes/scope_scene.c

@@ -0,0 +1,30 @@
+#include "../scope_app_i.h"
+
+// Generate scene on_enter handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
+void (*const scope_scene_on_enter_handlers[])(void*) = {
+#include "scope_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_event handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
+bool (*const scope_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
+#include "scope_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
+void (*const scope_scene_on_exit_handlers[])(void* context) = {
+#include "scope_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Initialize scene handlers configuration structure
+const SceneManagerHandlers scope_scene_handlers = {
+    .on_enter_handlers = scope_scene_on_enter_handlers,
+    .on_event_handlers = scope_scene_on_event_handlers,
+    .on_exit_handlers = scope_scene_on_exit_handlers,
+    .scene_num = ScopeSceneNum,
+};

+ 29 - 0
scenes/scope_scene.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include <gui/scene_manager.h>
+
+// Generate scene id and total number
+#define ADD_SCENE(prefix, name, id) ScopeScene##id,
+typedef enum {
+#include "scope_scene_config.h"
+    ScopeSceneNum,
+} ScopeScene;
+#undef ADD_SCENE
+
+extern const SceneManagerHandlers scope_scene_handlers;
+
+// Generate scene on_enter handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
+#include "scope_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_event handlers declaration
+#define ADD_SCENE(prefix, name, id) \
+    bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
+#include "scope_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
+#include "scope_scene_config.h"
+#undef ADD_SCENE

+ 59 - 0
scenes/scope_scene_about.c

@@ -0,0 +1,59 @@
+#include "../scope_app_i.h"
+
+void scope_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
+    ScopeApp* app = context;
+    if(type == InputTypeShort) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, result);
+    }
+}
+
+void scope_scene_about_on_enter(void* context) {
+    ScopeApp* app = context;
+
+    FuriString* temp_str;
+    temp_str = furi_string_alloc();
+    furi_string_printf(temp_str, "\e#%s\n", "Information");
+
+    furi_string_cat_printf(temp_str, "Version: %s\n", S_VERSION_APP);
+    furi_string_cat_printf(temp_str, "Developed by: %s\n", S_DEVELOPED);
+    furi_string_cat_printf(temp_str, "Github: %s\n\n", S_GITHUB);
+
+    widget_add_text_box_element(
+        app->widget,
+        0,
+        0,
+        128,
+        14,
+        AlignCenter,
+        AlignBottom,
+        "\e#\e!                                                      \e!\n",
+        false);
+    widget_add_text_box_element(
+        app->widget,
+        0,
+        2,
+        128,
+        14,
+        AlignCenter,
+        AlignBottom,
+        "\e#\e!          flipperscope             \e!\n",
+        false);
+    widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
+    furi_string_free(temp_str);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, ScopeViewWidget);
+}
+
+bool scope_scene_about_on_event(void* context, SceneManagerEvent event) {
+    ScopeApp* app = context;
+    bool consumed = false;
+    UNUSED(app);
+    UNUSED(event);
+    return consumed;
+}
+
+void scope_scene_about_on_exit(void* context) {
+    ScopeApp* app = context;
+    // Clear views
+    widget_reset(app->widget);
+}

+ 4 - 0
scenes/scope_scene_config.h

@@ -0,0 +1,4 @@
+ADD_SCENE(scope, start, Start)
+ADD_SCENE(scope, run, Run)
+ADD_SCENE(scope, setup, Setup)
+ADD_SCENE(scope, about, About)

+ 502 - 0
scenes/scope_scene_run.c

@@ -0,0 +1,502 @@
+#include <float.h>
+#include <furi.h>
+#include <furi_hal.h>
+#include <furi_hal_bus.h>
+#include <furi_hal_resources.h>
+#include <gui/gui.h>
+#include <gui/view_dispatcher.h>
+#include <gui/scene_manager.h>
+#include <gui/modules/submenu.h>
+#include <gui/modules/variable_item_list.h>
+#include <gui/modules/widget.h>
+#include <notification/notification_messages.h>
+
+#include "stm32wbxx_hal.h"
+#include "stm32wbxx_hal_tim.h"
+#include "stm32wbxx_nucleo.h"
+#include "stm32wbxx_hal_adc.h"
+#include "../scope_app_i.h"
+
+#define DIGITAL_SCALE_12BITS ((uint32_t)0xFFF)
+#define ADC_CONVERTED_DATA_BUFFER_SIZE ((uint32_t)128)
+#define VAR_CONVERTED_DATA_INIT_VALUE (DIGITAL_SCALE_12BITS + 1)
+#define VAR_CONVERTED_DATA_INIT_VALUE_16BITS (0xFFFF + 1U)
+#define __ADC_CALC_DATA_VOLTAGE(__VREFANALOG_VOLTAGE__, __ADC_DATA__) \
+    ((__ADC_DATA__) * (__VREFANALOG_VOLTAGE__) / DIGITAL_SCALE_12BITS)
+#define VDDA_APPLI ((uint32_t)2500)
+
+// ramVector found from - https://community.nxp.com/t5/i-MX-Processors/Relocate-vector-table-to-ITCM/m-p/1302304
+// the aligned aspect is key!
+#define TABLE_SIZE 79
+uint32_t ramVector[TABLE_SIZE + 1] __attribute__((aligned(512)));
+
+const uint32_t AHBPrescTable[16UL] =
+    {1UL, 3UL, 5UL, 1UL, 1UL, 6UL, 10UL, 32UL, 2UL, 4UL, 8UL, 16UL, 64UL, 128UL, 256UL, 512UL};
+const uint32_t APBPrescTable[8UL] = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
+const uint32_t MSIRangeTable[16UL] = {
+    100000UL,
+    200000UL,
+    400000UL,
+    800000UL,
+    1000000UL,
+    2000000UL,
+    4000000UL,
+    8000000UL,
+    16000000UL,
+    24000000UL,
+    32000000UL,
+    48000000UL,
+    0UL,
+    0UL,
+    0UL,
+    0UL}; /* 0UL values are incorrect cases */
+
+char* time; // Current time period text
+double freq; // Current samplerate
+uint8_t pause = 0; // Whether we want to pause output or not
+enum measureenum type; // Type of measurement we are performing
+int toggle = 0; // Used for toggling output GPIO, only used in testing
+
+void Error_Handler() {
+    while(1) {
+    }
+}
+
+static ADC_HandleTypeDef hadc1;
+static DMA_HandleTypeDef hdma_adc1;
+static TIM_HandleTypeDef htim2;
+
+__IO uint16_t
+    aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE]; // Array that ADC data is copied to, via DMA
+__IO uint16_t aADCxConvertedData_Voltage_mVoltA
+    [ADC_CONVERTED_DATA_BUFFER_SIZE]; // Data is converted to range from 0 to 2500
+__IO uint16_t aADCxConvertedData_Voltage_mVoltB
+    [ADC_CONVERTED_DATA_BUFFER_SIZE]; // Data is converted to range from 0 to 2500
+__IO uint8_t ubDmaTransferStatus = 2; // DMA transfer status
+
+__IO uint16_t* mvoltWrite =
+    &aADCxConvertedData_Voltage_mVoltA[0]; // Pointer to area we write converted voltage data to
+__IO uint16_t* mvoltDisplay =
+    &aADCxConvertedData_Voltage_mVoltB[0]; // Pointer to area of memory we display
+
+void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) {
+    GPIO_InitTypeDef GPIO_InitStruct = {0};
+    if(hadc->Instance == ADC1) {
+        __HAL_RCC_ADC_CLK_ENABLE();
+        __HAL_RCC_GPIOC_CLK_ENABLE();
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+        hdma_adc1.Instance = DMA1_Channel1;
+        hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
+        hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
+        hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
+        hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
+        hdma_adc1.Init.Mode = DMA_CIRCULAR;
+        hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
+        if(HAL_DMA_Init(&hdma_adc1) != HAL_OK) {
+            Error_Handler();
+        }
+        __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc1);
+        HAL_NVIC_SetPriority(ADC1_IRQn, 15, 0);
+        HAL_NVIC_EnableIRQ(ADC1_IRQn);
+    }
+}
+
+void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) {
+    if(hadc->Instance == ADC1) {
+        __HAL_RCC_ADC_CLK_DISABLE();
+        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0);
+        HAL_DMA_DeInit(hadc->DMA_Handle);
+        HAL_NVIC_DisableIRQ(ADC1_IRQn);
+    }
+}
+
+void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) {
+    if(htim_base->Instance == TIM2) {
+        __HAL_RCC_TIM2_CLK_ENABLE();
+        HAL_NVIC_SetPriority(TIM2_IRQn, 15, 0);
+        HAL_NVIC_EnableIRQ(TIM2_IRQn);
+    }
+}
+
+void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) {
+    if(htim_base->Instance == TIM2) {
+        __HAL_RCC_TIM2_CLK_DISABLE();
+        HAL_NVIC_DisableIRQ(TIM2_IRQn);
+    }
+}
+
+void DMA1_Channel1_IRQHandler(void) {
+    HAL_DMA_IRQHandler(&hdma_adc1);
+}
+
+void ADC1_IRQHandler(void) {
+    HAL_ADC_IRQHandler(&hadc1);
+}
+
+void TIM2_IRQHandler(void) {
+    HAL_TIM_IRQHandler(&htim2);
+}
+
+// Setup ADC1 to be triggered by timer2
+static void MX_ADC1_Init(void) {
+    ADC_ChannelConfTypeDef sConfig = {0};
+    hadc1.Instance = ADC1;
+    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
+    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
+    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
+    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
+    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
+    hadc1.Init.LowPowerAutoWait = DISABLE;
+    hadc1.Init.ContinuousConvMode = DISABLE;
+    hadc1.Init.NbrOfConversion = 1;
+    hadc1.Init.DiscontinuousConvMode = DISABLE;
+    hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
+    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
+    hadc1.Init.DMAContinuousRequests = ENABLE;
+    hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
+    hadc1.Init.OversamplingMode = DISABLE;
+    if(HAL_ADC_Init(&hadc1) != HAL_OK) {
+        Error_Handler();
+    }
+    sConfig.Channel = ADC_CHANNEL_1;
+    sConfig.Rank = ADC_REGULAR_RANK_1;
+    sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
+    sConfig.SingleDiff = ADC_SINGLE_ENDED;
+    sConfig.OffsetNumber = ADC_OFFSET_NONE;
+    sConfig.Offset = 0;
+    if(HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
+        Error_Handler();
+    }
+}
+
+// Only used in testing, for toggling GPIO pin, to measure timer frequency
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) {
+    if(htim->Instance == TIM2) {
+        toggle ^= 1;
+        furi_hal_gpio_write(&gpio_ext_pa7, toggle);
+    }
+}
+
+// Init timer2
+static void MX_TIM2_Init(uint32_t period) {
+    if(!furi_hal_bus_is_enabled(FuriHalBusTIM2)) {
+        furi_hal_bus_enable(FuriHalBusTIM2);
+    }
+    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
+    TIM_MasterConfigTypeDef sMasterConfig = {0};
+    htim2.Instance = TIM2;
+    htim2.Init.Prescaler = 1;
+    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
+    htim2.Init.Period = period;
+    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+    if(HAL_TIM_Base_Init(&htim2) != HAL_OK) {
+        Error_Handler();
+    }
+    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
+    if(HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
+        Error_Handler();
+    }
+    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
+    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+    if(HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) {
+        Error_Handler();
+    }
+}
+
+static void MX_DMA_Init(void) {
+    __HAL_RCC_DMAMUX1_CLK_ENABLE();
+    __HAL_RCC_DMA1_CLK_ENABLE();
+    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 15, 0);
+    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
+}
+
+static void MX_GPIO_Init(void) {
+    __HAL_RCC_GPIOC_CLK_ENABLE();
+}
+
+// Swap pointer addresses, used for double buffer
+void swap(__IO uint16_t** a, __IO uint16_t** b) {
+    __IO uint16_t* tmp;
+    tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+
+// Write end half of DMA buffer to converted output
+void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
+    UNUSED(hadc);
+    uint32_t tmp_index = 0;
+    for(tmp_index = (ADC_CONVERTED_DATA_BUFFER_SIZE / 2);
+        tmp_index < ADC_CONVERTED_DATA_BUFFER_SIZE;
+        tmp_index++) {
+        mvoltWrite[tmp_index] = __ADC_CALC_DATA_VOLTAGE(VDDA_APPLI, aADCxConvertedData[tmp_index]);
+    }
+    ubDmaTransferStatus = 1;
+    // Swap double buffer, so new data can be displayed, provided we're not paused
+    if(!pause) swap(&mvoltWrite, &mvoltDisplay);
+}
+
+// Write first half of DMA buffer to converted output
+void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
+    UNUSED(hadc);
+    uint32_t tmp_index = 0;
+    for(tmp_index = 0; tmp_index < (ADC_CONVERTED_DATA_BUFFER_SIZE / 2); tmp_index++) {
+        mvoltWrite[tmp_index] = __ADC_CALC_DATA_VOLTAGE(VDDA_APPLI, aADCxConvertedData[tmp_index]);
+    }
+    ubDmaTransferStatus = 0;
+}
+
+void HAL_ADC_ErrorCallback(ADC_HandleTypeDef* hadc) {
+    UNUSED(hadc);
+    Error_Handler();
+}
+
+// Used to draw to display
+static void app_draw_callback(Canvas* canvas, void* ctx) {
+    UNUSED(ctx);
+
+    static int16_t index[ADC_CONVERTED_DATA_BUFFER_SIZE];
+    static float data[ADC_CONVERTED_DATA_BUFFER_SIZE];
+    static float crossings[ADC_CONVERTED_DATA_BUFFER_SIZE];
+    static char buf1[50];
+
+    float max = 0.0;
+    float min = FLT_MAX;
+    int count = 0;
+
+    // Calculate voltage measurements
+    for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++) {
+        if(mvoltDisplay[x] < min) min = mvoltDisplay[x];
+        if(mvoltDisplay[x] > max) max = mvoltDisplay[x];
+    }
+    max /= 1000;
+    min /= 1000;
+
+    switch(type) {
+    case m_time: {
+        // Display current time period
+        snprintf(buf1, 50, "Time: %s", time);
+        canvas_draw_str(canvas, 10, 10, buf1);
+        // Shift waveform across a virtual 0 line, so it crosses 0
+        for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++) {
+            index[x] = -1;
+            crossings[x] = -1.0;
+            data[x] = ((float)mvoltDisplay[x] / 1000) - min;
+            data[x] = ((2 / (max - min)) * data[x]) - 1;
+        }
+        // Find points at which waveform crosses virtual 0 line
+        for(uint32_t x = 1; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++) {
+            if(data[x] >= 0 && data[x - 1] < 0) {
+                index[count++] = x - 1;
+            }
+        }
+        count = 0;
+        // Linear interpolation to find zero crossings
+        // see https://gist.github.com/endolith/255291 for Python version
+        for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++) {
+            if(index[x] == -1) break;
+            crossings[count++] =
+                (float)index[x] - data[index[x]] / (data[index[x] + 1] - data[index[x]]);
+        }
+        float avg = 0.0;
+        float countv = 0.0;
+        for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++) {
+            if(x + 1 >= ADC_CONVERTED_DATA_BUFFER_SIZE) break;
+            if(crossings[x] == -1 || crossings[x + 1] == -1) break;
+            avg += crossings[x + 1] - crossings[x];
+            countv += 1;
+        }
+        avg /= countv;
+        // Display frequency of waveform
+        snprintf(buf1, 50, "Freq: %.1f Hz", (double)((float)freq / avg));
+        canvas_draw_str(canvas, 10, 20, buf1);
+    } break;
+    case m_voltage: {
+        // Display max, min, peak-to-peak voltages
+        snprintf(buf1, 50, "Max: %.2fV", (double)max);
+        canvas_draw_str(canvas, 10, 10, buf1);
+        snprintf(buf1, 50, "Min: %.2fV", (double)min);
+        canvas_draw_str(canvas, 10, 20, buf1);
+        snprintf(buf1, 50, "Vpp: %.2fV", (double)(max - min));
+        canvas_draw_str(canvas, 10, 30, buf1);
+    } break;
+    default:
+        break;
+    }
+
+    // Draw lines between each data point
+    for(uint32_t x = 1; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++) {
+        uint32_t prev = 64 - (mvoltDisplay[x - 1] / (VDDA_APPLI / 64));
+        uint32_t cur = 64 - (mvoltDisplay[x] / (VDDA_APPLI / 64));
+        canvas_draw_line(canvas, x - 1, prev, x, cur);
+    }
+
+    // Draw graph lines
+    canvas_draw_line(canvas, 0, 0, 0, 63);
+    canvas_draw_line(canvas, 0, 63, 128, 63);
+}
+
+static void app_input_callback(InputEvent* input_event, void* ctx) {
+    furi_assert(ctx);
+    FuriMessageQueue* event_queue = ctx;
+    furi_message_queue_put(event_queue, input_event, FuriWaitForever);
+}
+
+void scope_scene_run_widget_callback(GuiButtonType result, InputType type, void* context) {
+    ScopeApp* app = context;
+    if(type == InputTypeShort) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, result);
+    }
+}
+
+void scope_scene_run_on_enter(void* context) {
+    ScopeApp* app = context;
+
+    // Find string representation of time period we're using
+    for(uint32_t i = 0; i < COUNT_OF(time_list); i++) {
+        if(time_list[i].time == app->time) {
+            time = time_list[i].str;
+            break;
+        }
+    }
+
+    // Currently un-paused
+    pause = 0;
+
+    // What type of measurement are we performing
+    type = app->measurement;
+
+    // Test purposes
+    //furi_hal_gpio_write(&gpio_ext_pa7, false);
+    //furi_hal_gpio_init( &gpio_ext_pa7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
+
+    // Copy vector table, modify to use our own IRQ handlers
+    __disable_irq();
+    memcpy(ramVector, (uint32_t*)(FLASH_BASE | SCB->VTOR), sizeof(uint32_t) * TABLE_SIZE);
+    SCB->VTOR = (uint32_t)ramVector;
+    ramVector[27] = (uint32_t)DMA1_Channel1_IRQHandler;
+    ramVector[34] = (uint32_t)ADC1_IRQHandler;
+    ramVector[44] = (uint32_t)TIM2_IRQHandler;
+    __enable_irq();
+
+    // Found this recommended by https://www.freertos.org/RTOS-Cortex-M3-M4.html
+    // although we're using after RTOS started
+    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
+
+    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
+
+    uint32_t tmp_index_adc_converted_data = 0;
+    MX_GPIO_Init();
+    MX_DMA_Init();
+
+    // Hack -- PCLK1 - seems to be twice what is reported? Not sure how?
+    uint32_t period = (uint32_t)((double)(HAL_RCC_GetPCLK1Freq() * 2) * app->time);
+    freq = 1 / app->time;
+
+    MX_TIM2_Init(period);
+
+    // Set VREFBUF to 2.5V, as vref isn't connected to 3.3V itself in the flipper zero
+    VREFBUF->CSR |= VREFBUF_CSR_ENVR;
+    VREFBUF->CSR &= ~VREFBUF_CSR_HIZ;
+    VREFBUF->CSR |= VREFBUF_CSR_VRS;
+    while(!(VREFBUF->CSR & VREFBUF_CSR_VRR)) {
+    };
+
+    MX_ADC1_Init();
+
+    // Setup initial values from ADC
+    for(tmp_index_adc_converted_data = 0;
+        tmp_index_adc_converted_data < ADC_CONVERTED_DATA_BUFFER_SIZE;
+        tmp_index_adc_converted_data++) {
+        aADCxConvertedData[tmp_index_adc_converted_data] = VAR_CONVERTED_DATA_INIT_VALUE;
+        aADCxConvertedData_Voltage_mVoltA[tmp_index_adc_converted_data] = 0;
+        aADCxConvertedData_Voltage_mVoltB[tmp_index_adc_converted_data] = 0;
+    }
+
+    if(HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK) {
+        Error_Handler();
+    }
+
+    // Use to generate interrupt to toggle GPIO for testing
+    //if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
+    if(HAL_TIM_Base_Start(&htim2) != HAL_OK) {
+        Error_Handler();
+    }
+
+    // Start DMA transfer
+    if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE) !=
+       HAL_OK) {
+        Error_Handler();
+    }
+
+    ViewPort* view_port = view_port_alloc();
+    view_port_draw_callback_set(view_port, app_draw_callback, view_port);
+    view_port_input_callback_set(view_port, app_input_callback, event_queue);
+
+    // Register view port in GUI
+    Gui* gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+    InputEvent event;
+    bool running = true;
+    while(running) {
+        if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
+            if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
+                switch(event.key) {
+                case InputKeyLeft:
+                    break;
+                case InputKeyRight:
+                    break;
+                case InputKeyUp:
+                    break;
+                case InputKeyDown:
+                    break;
+                case InputKeyOk:
+                    pause ^= 1;
+                    break;
+                default:
+                    running = false;
+                    break;
+                }
+            }
+        }
+        view_port_update(view_port);
+    }
+
+    // Stop DMA and switch back to original vector table
+    HAL_ADC_Stop_DMA(&hadc1);
+    __disable_irq();
+    SCB->VTOR = 0;
+    __enable_irq();
+
+    if(furi_hal_bus_is_enabled(FuriHalBusTIM2)) {
+        furi_hal_bus_disable(FuriHalBusTIM2);
+    }
+    view_port_enabled_set(view_port, false);
+    gui_remove_view_port(gui, view_port);
+    view_port_free(view_port);
+
+    // Switch back to original scene
+    furi_record_close(RECORD_GUI);
+    scene_manager_previous_scene(app->scene_manager);
+    submenu_set_selected_item(app->submenu, 0);
+}
+
+bool scope_scene_run_on_event(void* context, SceneManagerEvent event) {
+    ScopeApp* app = context;
+    bool consumed = false;
+    UNUSED(app);
+    UNUSED(event);
+    return consumed;
+}
+
+void scope_scene_run_on_exit(void* context) {
+    ScopeApp* app = context;
+    // Clear views
+    widget_reset(app->widget);
+}

+ 68 - 0
scenes/scope_scene_setup.c

@@ -0,0 +1,68 @@
+#include "../scope_app_i.h"
+
+void scope_scene_setup_widget_callback(GuiButtonType result, InputType type, void* context) {
+    ScopeApp* app = context;
+    if(type == InputTypeShort) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, result);
+    }
+}
+
+static void timeperiod_cb(VariableItem* item) {
+    ScopeApp* app = variable_item_get_context(item);
+    furi_assert(app);
+    uint8_t index = variable_item_get_current_value_index(item);
+    variable_item_set_current_value_text(item, time_list[index].str);
+    app->time = time_list[index].time;
+}
+
+static void measurement_cb(VariableItem* item) {
+    ScopeApp* app = variable_item_get_context(item);
+    furi_assert(app);
+    uint8_t index = variable_item_get_current_value_index(item);
+    variable_item_set_current_value_text(item, measurement_list[index].str);
+    app->measurement = measurement_list[index].type;
+}
+
+void scope_scene_setup_on_enter(void* context) {
+    ScopeApp* app = context;
+    VariableItemList* var_item_list = app->variable_item_list;
+    VariableItem* item;
+    item = variable_item_list_add(
+        var_item_list, "Time period", COUNT_OF(time_list), timeperiod_cb, app);
+
+    for(uint32_t i = 0; i < COUNT_OF(time_list); i++) {
+        if(time_list[i].time == app->time) {
+            variable_item_set_current_value_index(item, i);
+            variable_item_set_current_value_text(item, time_list[i].str);
+            break;
+        }
+    }
+
+    item = variable_item_list_add(
+        var_item_list, "Measurement", COUNT_OF(measurement_list), measurement_cb, app);
+
+    for(uint32_t i = 0; i < COUNT_OF(measurement_list); i++) {
+        if(measurement_list[i].type == app->measurement) {
+            variable_item_set_current_value_index(item, i);
+            variable_item_set_current_value_text(item, measurement_list[i].str);
+            break;
+        }
+    }
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, ScopeViewVariableItemList);
+}
+
+bool scope_scene_setup_on_event(void* context, SceneManagerEvent event) {
+    ScopeApp* app = context;
+    bool consumed = false;
+    UNUSED(app);
+    UNUSED(event);
+    return consumed;
+}
+
+void scope_scene_setup_on_exit(void* context) {
+    ScopeApp* app = context;
+    variable_item_list_reset(app->variable_item_list);
+    // Clear views
+    widget_reset(app->widget);
+}

+ 58 - 0
scenes/scope_scene_start.c

@@ -0,0 +1,58 @@
+#include "../scope_app_i.h"
+
+typedef enum {
+    SubmenuIndexScopeRun,
+    SubmenuIndexScopeSetup,
+    SubmenuIndexScopeAbout,
+} SubmenuIndex;
+
+void scope_scene_start_submenu_callback(void* context, uint32_t index) {
+    ScopeApp* app = context;
+    view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void scope_scene_start_on_enter(void* context) {
+    UNUSED(context);
+    ScopeApp* app = context;
+    Submenu* submenu = app->submenu;
+
+    submenu_add_item(
+        submenu, "Run", SubmenuIndexScopeRun, scope_scene_start_submenu_callback, app);
+
+    submenu_add_item(
+        submenu, "Setup", SubmenuIndexScopeSetup, scope_scene_start_submenu_callback, app);
+
+    submenu_add_item(
+        submenu, "About", SubmenuIndexScopeAbout, scope_scene_start_submenu_callback, app);
+
+    submenu_set_selected_item(
+        submenu, scene_manager_get_scene_state(app->scene_manager, ScopeSceneStart));
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, ScopeViewSubmenu);
+}
+
+bool scope_scene_start_on_event(void* context, SceneManagerEvent event) {
+    ScopeApp* app = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexScopeAbout) {
+            scene_manager_next_scene(app->scene_manager, ScopeSceneAbout);
+            consumed = true;
+        } else if(event.event == SubmenuIndexScopeRun) {
+            scene_manager_next_scene(app->scene_manager, ScopeSceneRun);
+            consumed = true;
+        } else if(event.event == SubmenuIndexScopeSetup) {
+            scene_manager_next_scene(app->scene_manager, ScopeSceneSetup);
+            consumed = true;
+        }
+        scene_manager_set_scene_state(app->scene_manager, ScopeSceneStart, event.event);
+    }
+
+    return consumed;
+}
+
+void scope_scene_start_on_exit(void* context) {
+    ScopeApp* app = context;
+    submenu_reset(app->submenu);
+}

+ 14 - 0
scenes/scope_types.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include <furi.h>
+#include <furi_hal.h>
+
+#define S_VERSION_APP "0.0.1"
+#define S_DEVELOPED "anfractuosity"
+#define S_GITHUB "https://github.com/anfractuosity/flipperscope"
+
+typedef enum {
+    ScopeViewVariableItemList,
+    ScopeViewSubmenu,
+    ScopeViewWidget,
+} ScopeView;

+ 120 - 0
scope.c

@@ -0,0 +1,120 @@
+#include <furi.h>
+#include <furi_hal.h>
+#include <furi_hal_resources.h>
+#include <gui/gui.h>
+#include <gui/view_dispatcher.h>
+#include <gui/scene_manager.h>
+#include <gui/modules/variable_item_list.h>
+#include <gui/modules/widget.h>
+#include <notification/notification_messages.h>
+
+#include "scope_app_i.h"
+
+void assert_failed(uint8_t* file, uint32_t line) {
+    UNUSED(file);
+    UNUSED(line);
+    while(1) {
+    }
+}
+
+static bool scope_app_custom_event_callback(void* context, uint32_t event) {
+    furi_assert(context);
+    ScopeApp* app = context;
+    return scene_manager_handle_custom_event(app->scene_manager, event);
+}
+
+static bool scope_app_back_event_callback(void* context) {
+    furi_assert(context);
+    ScopeApp* app = context;
+    return scene_manager_handle_back_event(app->scene_manager);
+}
+
+static void scope_app_tick_event_callback(void* context) {
+    furi_assert(context);
+    ScopeApp* app = context;
+    scene_manager_handle_tick_event(app->scene_manager);
+}
+
+ScopeApp* scope_app_alloc() {
+    ScopeApp* app = malloc(sizeof(ScopeApp));
+
+    // GUI
+    app->gui = furi_record_open(RECORD_GUI);
+
+    // View Dispatcher
+    app->view_dispatcher = view_dispatcher_alloc();
+    app->scene_manager = scene_manager_alloc(&scope_scene_handlers, app);
+    view_dispatcher_enable_queue(app->view_dispatcher);
+
+    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
+    view_dispatcher_set_custom_event_callback(
+        app->view_dispatcher, scope_app_custom_event_callback);
+    view_dispatcher_set_navigation_event_callback(
+        app->view_dispatcher, scope_app_back_event_callback);
+    view_dispatcher_set_tick_event_callback(
+        app->view_dispatcher, scope_app_tick_event_callback, 100);
+
+    view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
+
+    // Open Notification record
+    app->notifications = furi_record_open(RECORD_NOTIFICATION);
+
+    // Variable Item List
+    app->variable_item_list = variable_item_list_alloc();
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        ScopeViewVariableItemList,
+        variable_item_list_get_view(app->variable_item_list));
+
+    // SubMenu
+    app->submenu = submenu_alloc();
+    view_dispatcher_add_view(
+        app->view_dispatcher, ScopeViewSubmenu, submenu_get_view(app->submenu));
+
+    // Widget
+    app->widget = widget_alloc();
+    view_dispatcher_add_view(app->view_dispatcher, ScopeViewWidget, widget_get_view(app->widget));
+
+    app->time = 0.001;
+    app->measurement = m_time;
+
+    scene_manager_next_scene(app->scene_manager, ScopeSceneStart);
+    return app;
+}
+
+void scope_app_free(ScopeApp* app) {
+    furi_assert(app);
+
+    // Submenu
+    view_dispatcher_remove_view(app->view_dispatcher, ScopeViewSubmenu);
+    submenu_free(app->submenu);
+
+    // Variable Item List
+    view_dispatcher_remove_view(app->view_dispatcher, ScopeViewVariableItemList);
+    variable_item_list_free(app->variable_item_list);
+
+    //  Widget
+    view_dispatcher_remove_view(app->view_dispatcher, ScopeViewWidget);
+    widget_free(app->widget);
+
+    // View dispatcher
+    view_dispatcher_free(app->view_dispatcher);
+    scene_manager_free(app->scene_manager);
+
+    // Notifications
+    furi_record_close(RECORD_NOTIFICATION);
+    app->notifications = NULL;
+
+    // Close records
+    furi_record_close(RECORD_GUI);
+
+    free(app);
+}
+
+int32_t scope_main(void* p) {
+    UNUSED(p);
+    ScopeApp* scope_app = scope_app_alloc();
+    view_dispatcher_run(scope_app->view_dispatcher);
+    scope_app_free(scope_app);
+    return 0;
+}

BIN
scope_10px.png


+ 48 - 0
scope_app_i.h

@@ -0,0 +1,48 @@
+#pragma once
+
+#include "scenes/scope_types.h"
+#include "scenes/scope_scene.h"
+
+#include <gui/gui.h>
+#include <gui/view_dispatcher.h>
+#include <gui/scene_manager.h>
+#include <gui/modules/submenu.h>
+#include <gui/modules/variable_item_list.h>
+#include <gui/modules/widget.h>
+#include <notification/notification_messages.h>
+
+typedef struct ScopeApp ScopeApp;
+
+typedef struct {
+    double time;
+    char* str;
+} timeperiod;
+
+static const timeperiod time_list[] = {
+    {1.0, "1s"},
+    {0.1, "0.1s"},
+    {1e-3, "1ms"},
+    {0.1e-3, "0.1ms"},
+    {1e-6, "1us"},
+    {0.5e-6, "0.5us"}};
+
+enum measureenum { m_time, m_voltage };
+
+typedef struct {
+    enum measureenum type;
+    char* str;
+} measurement;
+
+static const measurement measurement_list[] = {{m_time, "Time"}, {m_voltage, "Voltage"}};
+
+struct ScopeApp {
+    Gui* gui;
+    ViewDispatcher* view_dispatcher;
+    SceneManager* scene_manager;
+    NotificationApp* notifications;
+    VariableItemList* variable_item_list;
+    Submenu* submenu;
+    Widget* widget;
+    double time;
+    enum measureenum measurement;
+};