aboutsummaryrefslogtreecommitdiff
path: root/stmhal/hal/l4/src
diff options
context:
space:
mode:
authorTobias Badertscher2016-03-09 15:48:08 +0100
committerDamien George2016-04-16 21:51:40 +0100
commitf4942db044e9f614a9fc7254bb72b3441a2362a2 (patch)
tree0b4896aa8beec5e5ee3a09c2b0352c75f37b748d /stmhal/hal/l4/src
parent2ba6677775b8704723435dc07e7b619f4c85c43d (diff)
stmhal: L4: Add basic STM32L4xx HAL files.
These files come from STM32Cube_FW_L4_V1.3.0, with Windows line endings converted to unix. Only basic HAL files are added. In addition the QSPI support is included to support later external QSPI flash as mass storage.
Diffstat (limited to 'stmhal/hal/l4/src')
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal.c660
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_adc.c2992
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_adc_ex.c2382
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_can.c1404
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_cortex.c492
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_dac.c1183
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_dac_ex.c620
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_dma.c899
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_flash.c773
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_flash_ex.c980
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_flash_ramfunc.c155
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_gpio.c562
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_i2c.c5227
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_i2c_ex.c350
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_pcd.c1255
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_pcd_ex.c323
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_pwr.c676
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_pwr_ex.c1176
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_qspi.c1981
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_rcc.c1439
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_rcc_ex.c2009
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_rng.c519
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_rtc.c1530
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_rtc_ex.c1876
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_sd.c3412
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_spi.c2769
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_spi_ex.c133
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_tim.c5383
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_tim_ex.c2711
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_uart.c2117
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_hal_uart_ex.c462
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_ll_sdmmc.c496
-rw-r--r--stmhal/hal/l4/src/stm32l4xx_ll_usb.c1630
33 files changed, 50576 insertions, 0 deletions
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal.c b/stmhal/hal/l4/src/stm32l4xx_hal.c
new file mode 100644
index 000000000..c8a4a44ae
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal.c
@@ -0,0 +1,660 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief HAL module driver.
+ * This is the common part of the HAL initialization
+ *
+ @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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup HAL HAL
+ * @brief HAL module driver
+ * @{
+ */
+
+#ifdef HAL_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/**
+ * @brief STM32L4xx HAL Driver version number V1.3.0
+ */
+#define __STM32L4xx_HAL_VERSION_MAIN (0x01) /*!< [31:24] main version */
+#define __STM32L4xx_HAL_VERSION_SUB1 (0x03) /*!< [23:16] sub1 version */
+#define __STM32L4xx_HAL_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */
+#define __STM32L4xx_HAL_VERSION_RC (0x00) /*!< [7:0] release candidate */
+#define __STM32L4xx_HAL_VERSION ((__STM32L4xx_HAL_VERSION_MAIN << 24)\
+ |(__STM32L4xx_HAL_VERSION_SUB1 << 16)\
+ |(__STM32L4xx_HAL_VERSION_SUB2 << 8 )\
+ |(__STM32L4xx_HAL_VERSION_RC))
+
+#if defined(VREFBUF)
+#define VREFBUF_TIMEOUT_VALUE (uint32_t)10 /* 10 ms (to be confirmed) */
+#endif /* VREFBUF */
+
+/* ------------ SYSCFG registers bit address in the alias region ------------ */
+#define SYSCFG_OFFSET (SYSCFG_BASE - PERIPH_BASE)
+/* --- MEMRMP Register ---*/
+/* Alias word address of FB_MODE bit */
+#define MEMRMP_OFFSET SYSCFG_OFFSET
+#define FB_MODE_BitNumber ((uint8_t)0x8)
+#define FB_MODE_BB (PERIPH_BB_BASE + (MEMRMP_OFFSET * 32) + (FB_MODE_BitNumber * 4))
+
+/* --- SCSR Register ---*/
+/* Alias word address of SRAM2ER bit */
+#define SCSR_OFFSET (SYSCFG_OFFSET + 0x18)
+#define BRER_BitNumber ((uint8_t)0x0)
+#define SCSR_SRAM2ER_BB (PERIPH_BB_BASE + (SCSR_OFFSET * 32) + (BRER_BitNumber * 4))
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+__IO uint32_t uwTick;
+
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup HAL_Exported_Functions HAL Exported Functions
+ * @{
+ */
+
+/** @defgroup HAL_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 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 Configure the Flash prefetch, the Instruction and Data caches,
+ * the time base source, NVIC and any required global low level hardware
+ * by calling the HAL_MspInit() callback function to be optionally defined in user file
+ * stm32l4xx_hal_msp.c.
+ *
+ * @note HAL_Init() function is called at the beginning of program after reset and before
+ * the clock configuration.
+ *
+ * @note In the default implementation the System Timer (Systick) is used as source of time base.
+ * The Systick configuration is based on MSI clock, as MSI is the clock
+ * used after a system Reset and the NVIC configuration is set to Priority group 4.
+ * Once done, time base tick starts incrementing: the tick variable counter is incremented
+ * each 1ms in the SysTick_Handler() interrupt handler.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_Init(void)
+{
+ /* Configure Flash prefetch, Instruction cache, Data cache */
+ /* Default configuration at reset is: */
+ /* - Prefetch disabled */
+ /* - Instruction cache enabled */
+ /* - Data cache enabled */
+#if (INSTRUCTION_CACHE_ENABLE == 0)
+ __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+#endif /* INSTRUCTION_CACHE_ENABLE */
+
+#if (DATA_CACHE_ENABLE == 0)
+ __HAL_FLASH_DATA_CACHE_DISABLE();
+#endif /* DATA_CACHE_ENABLE */
+
+#if (PREFETCH_ENABLE != 0)
+ __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) */
+ HAL_InitTick(TICK_INT_PRIORITY);
+
+ /* Init the low level hardware */
+ HAL_MspInit();
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief De-initialize common part of the HAL and stop 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_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 DeInitialize 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)
+{
+ /*Configure the SysTick to have interrupt in 1ms time basis*/
+ HAL_SYSTICK_Config(SystemCoreClock/1000);
+
+ /*Configure the SysTick IRQ priority */
+ HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_Exported_Functions_Group2 HAL Control functions
+ * @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 identifier
+ (+) Get the device revision 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++;
+}
+
+/**
+ * @brief Provide 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 Provide accurate 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 = 0;
+ tickstart = HAL_GetTick();
+ while((HAL_GetTick() - tickstart) < Delay)
+ {
+ }
+}
+
+/**
+ * @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 */
+ 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 */
+ SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
+}
+
+/**
+ * @brief Return the HAL revision.
+ * @retval version : 0xXYZR (8bits for each decimal, R for RC)
+ */
+uint32_t HAL_GetHalVersion(void)
+{
+ return __STM32L4xx_HAL_VERSION;
+}
+
+/**
+ * @brief Return the device revision identifier.
+ * @retval Device revision identifier
+ */
+uint32_t HAL_GetREVID(void)
+{
+ return((DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID) >> 16);
+}
+
+/**
+ * @brief Return the device identifier.
+ * @retval Device identifier
+ */
+uint32_t HAL_GetDEVID(void)
+{
+ return(DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_Exported_Functions_Group3 HAL Debug functions
+ * @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 STOP0/STOP1/STOP2 modes
+ (+) Enable/Disable Debug module during STANDBY mode
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the Debug Module during SLEEP mode.
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGSleepMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
+}
+
+/**
+ * @brief Disable the Debug Module during SLEEP mode.
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGSleepMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
+}
+
+/**
+ * @brief Enable the Debug Module during STOP0/STOP1/STOP2 modes.
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStopMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
+}
+
+/**
+ * @brief Disable the Debug Module during STOP0/STOP1/STOP2 modes.
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGStopMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
+}
+
+/**
+ * @brief Enable the Debug Module during STANDBY mode.
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStandbyMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
+}
+
+/**
+ * @brief Disable the Debug Module during STANDBY mode.
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGStandbyMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_Exported_Functions_Group4 HAL SYSCFG configuration functions
+ * @brief HAL SYSCFG configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL SYSCFG configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start a hardware SRAM2 erase operation
+ (+) Enable/Disable the Internal FLASH Bank Swapping
+ (+) Configure the Voltage reference buffer
+ (+) Enable/Disable the Voltage reference buffer
+ (+) Enable/Disable the I/O analog switch voltage booster
+
+@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 */
+ SYSCFG->SKR = 0xCA;
+ SYSCFG->SKR = 0x53;
+ /* Starts a hardware SRAM2 erase operation*/
+ *(__IO uint32_t *) SCSR_SRAM2ER_BB = (uint8_t)0x00000001;
+}
+
+/**
+ * @brief Enable the Internal FLASH Bank Swapping.
+ *
+ * @note This function can be used only for STM32L4xx devices.
+ *
+ * @note Flash Bank2 mapped at 0x08000000 (and aliased @0x00000000)
+ * and Flash Bank1 mapped at 0x08100000 (and aliased at 0x00100000)
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_EnableMemorySwappingBank(void)
+{
+ *(__IO uint32_t *)FB_MODE_BB = (uint32_t)ENABLE;
+}
+
+/**
+ * @brief Disable the Internal FLASH Bank Swapping.
+ *
+ * @note This function can be used only for STM32L4xx devices.
+ *
+ * @note The default state : Flash Bank1 mapped at 0x08000000 (and aliased @0x0000 0000)
+ * and Flash Bank2 mapped at 0x08100000 (and aliased at 0x00100000)
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_DisableMemorySwappingBank(void)
+{
+
+ *(__IO uint32_t *)FB_MODE_BB = (uint32_t)DISABLE;
+}
+
+#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 SYSCFG_VREFBUF_VOLTAGE_SCALE0: VREF_OUT1 around 2.048 V.
+ * This requires VDDA equal to or higher than 2.4 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE1: VREF_OUT1 around 2.5 V.
+ * This requires VDDA equal to or higher than 2.8 V.
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(VoltageScaling));
+
+ MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_VRS, VoltageScaling);
+}
+
+/**
+ * @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 SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE: VREF+ pin is internally connect to VREFINT output.
+ * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE: VREF+ pin is high impedance.
+ * @retval None
+ */
+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).
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue));
+
+ MODIFY_REG(VREFBUF->CCR, VREFBUF_CCR_TRIM, TrimmingValue);
+}
+
+/**
+ * @brief Enable the Internal Voltage Reference buffer (VREFBUF).
+ * @retval HAL_OK/HAL_TIMEOUT
+ */
+HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void)
+{
+ uint32_t tickstart = 0;
+
+ SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait for VRR bit */
+ while(READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == RESET)
+ {
+ 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)
+{
+ CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR);
+}
+#endif /* VREFBUF */
+
+/**
+ * @brief Enable the I/O analog switch voltage booster
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_EnableIOAnalogSwitchBooster(void)
+{
+ SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN);
+}
+
+/**
+ * @brief Disable the I/O analog switch voltage booster
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_DisableIOAnalogSwitchBooster(void)
+{
+ CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_adc.c b/stmhal/hal/l4/src/stm32l4xx_hal_adc.c
new file mode 100644
index 000000000..0d2f29ff6
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_adc.c
@@ -0,0 +1,2992 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_adc.c
+ * @author MCD Application conversion
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC)
+ * peripheral:
+ * + Initialization and de-initialization functions
+ * ++ Configuration of ADC
+ * + Operation functions
+ * ++ Start, stop, get result of regular conversions of regular
+ * using 3 possible modes: polling, interruption or DMA.
+ * + Control functions
+ * ++ Analog Watchdog configuration
+ * ++ Channels configuration on regular group
+ * + State functions
+ * ++ ADC state machine management
+ * ++ Interrupts and flags management
+ *
+ @verbatim
+ ==============================================================================
+ ##### ADC specific 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 and overrun events.
+
+ (#) Single and continuous conversion modes.
+
+ (#) Scan mode for automatic conversion of channel 0 to channel 'n'.
+
+ (#) Data alignment with in-built data coherency.
+
+ (#) Channel-wise programmable sampling time.
+
+ (#) External trigger (timer or EXTI) with configurable polarity for
+ regular groups.
+
+ (#) DMA request generation for transfer of regular group converted data.
+
+ (#) Configurable delay between conversions in Dual interleaved mode.
+
+ (#) ADC channels selectable single/differential input.
+
+ (#) ADC offset on regular groups.
+
+ (#) 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 #####
+ ==============================================================================
+ [..]
+
+ (#) Enable the ADC interface
+ As prerequisite, in HAL_ADC_MspInit(), ADC clock source must be
+ configured at RCC top level.
+
+ Two different clock sources are available:
+ (++) - the ADC clock can be a specific clock source, coming from the system
+ clock, the PLLSAI1 or the PLLSAI2 running up to 80MHz.
+ (++) - or the ADC clock can be derived from the AHB clock of the ADC bus
+ interface, divided by a programmable factor
+
+
+ (++) For example, in case of PLLSAI2:
+ (+++) __HAL_RCC_ADC_CLK_ENABLE();
+ (+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
+ (+++) where
+ (+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC
+ (+++) PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI2
+
+
+ (#) ADC pins configuration
+ (++) Enable the clock for the ADC GPIOs using the following function:
+ __HAL_RCC_GPIOx_CLK_ENABLE();
+ (++) Configure these ADC pins in analog mode using HAL_GPIO_Init();
+
+ (#) Configure the ADC parameters (conversion resolution, data alignment,
+ continuous mode, ...) using the HAL_ADC_Init() function.
+
+ (#) Optionally, perform an automatic ADC calibration to improve the
+ conversion accuracy using function HAL_ADCEx_Calibration_Start().
+
+ (#) Activate the ADC peripheral using one of the start functions:
+ HAL_ADC_Start(), HAL_ADC_Start_IT(), HAL_ADC_Start_DMA(),
+ HAL_ADCEx_InjectedStart(), HAL_ADCEx_InjectedStart_IT() or
+ HAL_ADCEx_MultiModeStart_DMA() when multimode feature is available.
+
+ *** Channels to regular group configuration ***
+ ============================================
+ [..]
+ (+) To configure the ADC regular group features, use
+ HAL_ADC_Init() and HAL_ADC_ConfigChannel() functions.
+ (+) To activate the continuous mode, use the HAL_ADC_Init() function.
+ (+) To read the ADC converted values, use the HAL_ADC_GetValue() function.
+
+ *** DMA for regular configuration ***
+ =============================================================
+ [..]
+ (+) To enable the DMA mode for regular group, use the
+ HAL_ADC_Start_DMA() function.
+ (+) To enable the generation of DMA requests continuously at the end of
+ the last DMA transfer, resort to DMAContinuousRequests parameter of
+ ADC handle initialization structure.
+
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_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 ((uint32_t)(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 */
+
+#define ADC_CFGR2_FIELDS ((uint32_t)(ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR |\
+ ADC_CFGR2_OVSS | ADC_CFGR2_TROVS |\
+ ADC_CFGR2_ROVSM)) /*!< ADC_CFGR2 fields of parameters that can be updated when no conversion
+ (neither regular nor injected) is on-going */
+
+#define ADC_CFGR_WD_FIELDS ((uint32_t)(ADC_CFGR_AWD1SGL | ADC_CFGR_JAWD1EN | \
+ ADC_CFGR_AWD1EN | ADC_CFGR_AWD1CH)) /*!< ADC_CFGR fields of Analog Watchdog parameters that can be updated when no
+ conversion (neither regular nor injected) is on-going */
+
+#define ADC_OFR_FIELDS ((uint32_t)(ADC_OFR1_OFFSET1 | ADC_OFR1_OFFSET1_CH | ADC_OFR1_OFFSET1_EN)) /*!< ADC_OFR fields of parameters that can be updated when no conversion
+ (neither regular nor injected) is on-going */
+
+
+
+/* Delay to wait before setting ADEN once ADCAL has been reset
+ must be at least 4 ADC clock cycles.
+ Assuming lowest ADC clock (140 KHz according to DS), this
+ 4 ADC clock cycles duration is equal to
+ 4 / 140,000 = 0.028 ms.
+ ADC_ENABLE_TIMEOUT set to 2 is a margin large enough to ensure
+ the 4 ADC clock cycles have elapsed while waiting for ADRDY
+ to become 1 */
+ #define ADC_ENABLE_TIMEOUT ((uint32_t) 2) /*!< ADC enable time-out value */
+ #define ADC_DISABLE_TIMEOUT ((uint32_t) 2) /*!< ADC disable time-out value */
+
+
+
+/* Delay for ADC voltage regulator startup time */
+/* Maximum delay is 10 microseconds */
+/* (refer device RM, parameter Tadcvreg_stup). */
+#define ADC_STAB_DELAY_US ((uint32_t) 10) /*!< ADC voltage regulator startup time */
+
+
+/* Timeout to wait for current conversion on going to be completed. */
+/* Timeout fixed to worst case, for 1 channel. */
+/* - maximum sampling time (640.5 adc_clk) */
+/* - ADC resolution (Tsar 12 bits= 12.5 adc_clk) */
+/* - ADC clock with prescaler 256 */
+/* 653 * 256 = 167168 clock cycles max */
+/* Unit: cycles of CPU clock. */
+#define ADC_CONVERSION_TIME_MAX_CPU_CYCLES ((uint32_t) 167168) /*!< ADC conversion completion time-out value */
+
+
+
+
+/**
+ * @}
+ */
+
+/* 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 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
+ * depending on possible clock sources: System/PLLSAI1/PLLSAI2 clocks
+ * or AHB clock.
+ * @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 by 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".
+ * @note Parameters related to common ADC registers (ADC clock mode) are set
+ * only if all ADCs are disabled.
+ * If this is not the case, these common parameters setting are
+ * bypassed without error reporting: it can be the intended behaviour in
+ * case of update of a parameter of ADC_InitTypeDef on the fly,
+ * without disabling the other ADCs.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ ADC_Common_TypeDef *tmpADC_Common;
+ uint32_t tmpCFGR = 0;
+ uint32_t wait_loop_index = 0;
+
+ /* 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->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));
+ 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 can't be set at the same time */
+ assert_param(!((hadc->Init.DiscontinuousConvMode == ENABLE) && (hadc->Init.ContinuousConvMode == ENABLE)));
+
+
+ /* Actions performed only if ADC is coming from state reset: */
+ /* - Initialization of ADC MSP */
+ if (hadc->State == HAL_ADC_STATE_RESET)
+ {
+ /* Init the low level hardware */
+ HAL_ADC_MspInit(hadc);
+
+ /* 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 */
+ /* Exit deep power down mode if still in that state */
+ if (HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_DEEPPWD))
+ {
+ /* Exit deep power down mode */
+ CLEAR_BIT(hadc->Instance->CR, ADC_CR_DEEPPWD);
+
+ /* 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 */
+ }
+
+
+ if (HAL_IS_BIT_CLR(hadc->Instance->CR, ADC_CR_ADVREGEN))
+ {
+ /* Enable ADC internal voltage regulator then
+ wait for start-up time */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADVREGEN);
+ wait_loop_index = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(wait_loop_index != 0)
+ {
+ 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 (HAL_IS_BIT_CLR(hadc->Instance->CR, ADC_CR_ADVREGEN))
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ tmp_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). */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL) &&
+ (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET) )
+ {
+
+ /* Initialize the ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL);
+
+ /* Configuration of common ADC parameters */
+
+ /* Pointer to the common control register */
+ tmpADC_Common = ADC_COMMON_REGISTER(hadc);
+
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - clock configuration */
+ if ((ADC_IS_ENABLE(hadc) == RESET) &&
+ (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )
+ {
+ /* 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() ) */
+
+ MODIFY_REG(tmpADC_Common->CCR, ADC_CCR_PRESC|ADC_CCR_CKMODE, 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(hadc->Init.ContinuousConvMode) |
+ hadc->Init.Overrun |
+ hadc->Init.DataAlign |
+ hadc->Init.Resolution |
+ ADC_CFGR_REG_DISCONTINUOUS(hadc->Init.DiscontinuousConvMode) |
+ ADC_CFGR_DISCONTINUOUS_NUM(hadc->Init.NbrOfDiscConversion) );
+
+ /* Enable external trigger if trigger selection is different of software */
+ /* start. */
+ /* - external trigger to start conversion Init.ExternalTrigConv */
+ /* - external trigger polarity Init.ExternalTrigConvEdge */
+ /* Note: parameter ExternalTrigConvEdge set to "trigger edge none" is */
+ /* equivalent to software start. */
+ if ((hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
+ && (hadc->Init.ExternalTrigConvEdge != ADC_EXTERNALTRIGCONVEDGE_NONE))
+ {
+ tmpCFGR |= ( hadc->Init.ExternalTrigConv | 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 */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET)
+ {
+ tmpCFGR = ( ADC_CFGR_AUTOWAIT(hadc->Init.LowPowerAutoWait) |
+ ADC_CFGR_DMACONTREQ(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));
+
+ if ((hadc->Init.ExternalTrigConv == ADC_SOFTWARE_START)
+ || (hadc->Init.ExternalTrigConvEdge == ADC_EXTERNALTRIGCONVEDGE_NONE))
+ {
+ /* Multi trigger is not applicable to software-triggered conversions */
+ assert_param((hadc->Init.Oversampling.TriggeredMode == ADC_TRIGGEREDMODE_SINGLE_TRIGGER));
+ }
+
+
+ /* Configuration of Oversampler: */
+ /* - Oversampling Ratio */
+ /* - Right bit shift */
+ /* - Triggered mode */
+ /* - Oversampling mode (continued/resumed) */
+ MODIFY_REG(hadc->Instance->CFGR2, ADC_CFGR2_FIELDS,
+ ADC_CFGR2_ROVSE |
+ hadc->Init.Oversampling.Ratio |
+ hadc->Init.Oversampling.RightBitShift |
+ hadc->Init.Oversampling.TriggeredMode |
+ hadc->Init.Oversampling.OversamplingStopReset);
+ }
+ else
+ {
+ /* Disable Regular OverSampling */
+ CLEAR_BIT( hadc->Instance->CFGR2, ADC_CFGR2_ROVSE);
+ }
+
+
+ } /* if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET) */
+
+
+
+
+ /* 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);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ tmp_status = HAL_ERROR;
+ } /* if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL) && (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET) ) */
+
+
+ /* Return function status */
+ return tmp_status;
+
+}
+
+/**
+ * @brief Deinitialize the ADC peripheral registers to their default reset
+ * values, with deinitialization of the ADC MSP.
+ * @note Keep in mind that all ADCs use the same clock: disabling
+ * the clock will reset all ADCs.
+ * @note By default, HAL_ADC_DeInit() sets DEEPPWD: this saves more power by
+ * reducing the leakage currents and is particularly interesting before
+ * entering STOP 1 or STOP 2 modes.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef* hadc)
+{
+ /* Check ADC handle */
+ if(hadc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL);
+
+ /* Stop potential conversion on going, on regular and injected groups */
+ /* No check on ADC_ConversionStop() return status, if the conversion
+ stop failed, it is up to HAL_ADC_MspDeInit() to reset the ADC IP */
+ ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+
+ /* 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);
+
+ /* Disable the ADC peripheral */
+ /* No check on ADC_Disable() return status, if the ADC disabling process
+ failed, it is up to HAL_ADC_MspDeInit() to reset the ADC IP */
+ ADC_Disable(hadc);
+
+
+ /* ========== Reset ADC registers ========== */
+ /* Reset register IER */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_AWD3 | ADC_IT_AWD2 | ADC_IT_AWD1 |
+ ADC_IT_JQOVF | ADC_IT_OVR |
+ ADC_IT_JEOS | ADC_IT_JEOC |
+ 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_JQOVF | ADC_FLAG_OVR |
+ ADC_FLAG_JEOS | ADC_FLAG_JEOC |
+ ADC_FLAG_EOS | ADC_FLAG_EOC |
+ 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);
+
+
+
+
+
+
+ /* ========== Reset common ADC registers ========== */
+
+ /* Software is allowed to change common parameters only when all the other
+ ADCs are disabled. */
+ if ((ADC_IS_ENABLE(hadc) == RESET) &&
+ (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )
+ {
+ /* 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.
+
+ */
+ HAL_ADC_MspDeInit(hadc);
+
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+ /* Reset injected channel configuration parameters */
+ hadc->InjectionConfig.ContextQueue = 0;
+ hadc->InjectionConfig.ChannelCount = 0;
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_RESET;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+
+ /* Return function status */
+ return HAL_OK;
+
+}
+
+/**
+ * @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 ADCs use the same clock: disabling the clock will reset all ADCs.
+ * @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.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group2 Input and Output operation functions
+ * @brief 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.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * if ADC is Slave, ADC is enabled but conversion is not started,
+ * if ADC is master, ADC is enabled and multimode conversion is started.
+ * @param hadc: ADC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
+{
+ ADC_TypeDef *tmpADC_Master;
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+
+ /* if a regular conversion is already on-going (i.e. ADSTART is set),
+ don't restart the conversion. */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc))
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* State machine update: Check if an injected conversion is ongoing */
+ 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
+ {
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+ /* Clear HAL_ADC_STATE_READY and regular conversion results bits, set HAL_ADC_STATE_REG_BUSY bit */
+ 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);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - by default if ADC is Master or Independent or if multimode feature is not available
+ - if multimode setting is set to independent mode (no dual regular or injected conversions are configured) */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* 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));
+
+ /* Enable conversion of regular group. */
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion starts at next */
+ /* trigger event. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* - if ADC is slave and dual regular conversions are enabled, ADC is */
+ /* enabled only (conversion is not started), */
+ /* - if ADC is master, ADC is enabled and conversion is started. */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc))
+ {
+ /* Multimode feature is not available or ADC Instance is Independent or Master,
+ or is not Slave ADC with dual regular conversions enabled.
+ Then, set HAL_ADC_STATE_INJ_BUSY bit and reset HAL_ADC_STATE_INJ_EOC bit if JAUTO is set. */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ }
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ /* Start ADC */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADSTART);
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ /* if Master ADC JAUTO bit is set, update Slave State in setting
+ HAL_ADC_STATE_INJ_BUSY bit and in resetting HAL_ADC_STATE_INJ_EOC bit */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ if (READ_BIT(tmpADC_Master->CFGR, ADC_CFGR_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+
+ } /* if (READ_BIT(tmpADC_Master->CFGR, ADC_CFGR_JAUTO) != RESET) */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ } /* if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc)) */
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_status;
+ }
+}
+
+/**
+ * @brief Stop ADC conversion of regular and injected groups, disable ADC peripheral.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular and injected on-going conversions */
+ tmp_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_status == HAL_OK)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_REG_BUSY|HAL_ADC_STATE_INJ_BUSY), HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+
+/**
+ * @brief Wait for regular group conversion to be completed.
+ * @param hadc: ADC handle
+ * @param Timeout: Timeout value in millisecond.
+ * @note Depending on hadc->Init.EOCSelection, EOS or EOC is
+ * checked and cleared depending on AUTDLY bit status.
+ * @note HAL_ADC_PollForConversion() returns HAL_ERROR if EOC is polled in a
+ * DMA-managed conversions configuration: indeed, EOC is immediately
+ * reset by the DMA reading the DR register when the converted data is
+ * available. Therefore, EOC is set for a too short period to be
+ * reliably polled.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t tmp_Flag_End = 0x00;
+ ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_cfgr = 0x00;
+ uint32_t tmp_eos_raised = 0x01; /* by default, assume that EOS is set,
+ tmp_eos_raised will be corrected
+ accordingly during API execution */
+
+ /* 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_EOS;
+ }
+ else /* end of conversion selected */
+ {
+ /* Check that the ADC is not in a DMA-based configuration. Otherwise,
+ returns an error. */
+
+ /* Check whether dual regular conversions are disabled or unavailable. */
+ if (ADC_IS_DUAL_REGULAR_CONVERSION_ENABLE(hadc) == RESET)
+ {
+ /* Check DMAEN bit in handle ADC CFGR register */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_DMAEN) != RESET)
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Else need to check Common register CCR MDMA bit field. */
+ if (ADC_MULTIMODE_DMA_ENABLED())
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+ }
+
+ /* no DMA transfer detected, polling ADC_FLAG_EOC is possible */
+ tmp_Flag_End = ADC_FLAG_EOC;
+ }
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* Wait until End of Conversion or Sequence flag is raised */
+ while (HAL_IS_BIT_CLR(hadc->Instance->ISR, tmp_Flag_End))
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Next, to clear the polled flag as well as to update the handle State,
+ EOS is checked and the relevant configuration register is retrieved. */
+ /* 1. Check whether or not EOS is set */
+ if (HAL_IS_BIT_CLR(hadc->Instance->ISR, ADC_FLAG_EOS))
+ {
+ tmp_eos_raised = 0;
+ }
+ /* 2. Check whether or not hadc is the handle of a Slave ADC with dual
+ regular conversions enabled. */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc))
+ {
+ /* Retrieve handle ADC CFGR register */
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* Retrieve Master ADC CFGR register */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* 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(). */
+ /* For regular groups, no new conversion will start before EOC is cleared.*/
+ /* Note that 1. reading DR clears EOC. */
+ /* 2. in multimode with dual regular conversions enabled (when */
+ /* multimode feature is available), Master AUTDLY bit is */
+ /* checked. */
+ if (READ_BIT (tmp_cfgr, ADC_CFGR_AUTDLY) == RESET)
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
+ }
+ }
+
+
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+ /* If 1. EOS is set
+ 2. conversions are software-triggered
+ 3. CONT bit is reset (that of handle ADC or Master ADC if applicable)
+ Then regular conversions are over and HAL_ADC_STATE_REG_BUSY can be reset.
+ 4. additionally, if no injected conversions are on-going, HAL_ADC_STATE_READY
+ can be set */
+ if ((tmp_eos_raised)
+ && (ADC_IS_SOFTWARE_START_REGULAR(hadc))
+ && (READ_BIT (tmp_cfgr, ADC_CFGR_CONT) == RESET))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+ /* If no injected conversion on-going, set HAL_ADC_STATE_READY bit */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+
+
+ /* Return API HAL 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_AWD_EVENT ADC Analog watchdog 1 event
+ * @arg @ref ADC_AWD2_EVENT ADC Analog watchdog 2 event
+ * @arg @ref ADC_AWD3_EVENT ADC Analog watchdog 3 event
+ * @arg @ref ADC_OVR_EVENT ADC Overrun event
+ * @arg @ref ADC_JQOVF_EVENT ADC Injected context queue overflow event
+ * @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, DR 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));
+
+ tickstart = HAL_GetTick();
+
+ /* Check selected event flag */
+ while(__HAL_ADC_GET_FLAG(hadc, EventType) == RESET)
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ /* 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:
+ /* Change 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_AWD/2/3 function. */
+ /* For example: "if (HAL_ADC_GetState(hadc1) == HAL_ADC_STATE_AWD) " */
+ /* "if (HAL_ADC_GetState(hadc1) == HAL_ADC_STATE_AWD2)" */
+ /* "if (HAL_ADC_GetState(hadc1) == HAL_ADC_STATE_AWD3)" */
+ case ADC_AWD_EVENT:
+ /* Change 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:
+ /* Change 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:
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+ /* Clear ADC analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD3);
+
+ break;
+
+ /* Injected context queue overflow event */
+ case ADC_JQOVF_EVENT:
+ /* Change 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;
+
+ /* 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)
+ {
+ /* Change 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, DR is potentially overwritten by new converted data as soon
+ as OVR is cleared. */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+ }
+ break;
+ }
+
+ /* Return API HAL 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 Case of multimode enabled (when multimode feature is available):
+ * HAL_ADC_Start_IT() must be called for ADC Slave first, then for
+ * ADC Master.
+ * For ADC Slave, ADC is enabled only (conversion is not started).
+ * For ADC Master, ADC is enabled and multimode conversion is started.
+ * @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() doesn't 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_status = HAL_OK;
+ ADC_TypeDef *tmpADC_Master;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* if a regular conversion is already on-going (i.e. ADSTART is set),
+ don't restart the conversion. */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc))
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* State machine update: Check if an injected conversion is ongoing */
+ 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
+ {
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+ /* Clear HAL_ADC_STATE_READY and regular conversion results bits, set HAL_ADC_STATE_REG_BUSY bit */
+ 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);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - by default if ADC is Master or Independent or if multimode feature is not available
+ - if MultiMode setting is set to independent mode (no dual regular or injected conversions are configured) */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* 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));
+
+ /* By default, disable all interruptions before enabling the desired ones */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+ /* Enable required interruptions */
+ 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;
+ }
+
+ /* 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 starts at next */
+ /* trigger event. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* - if ADC is slave and dual regular conversions are enabled, ADC is */
+ /* enabled only (conversion is not started), */
+ /* - if ADC is master, ADC is enabled and conversion is started. */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc) )
+ {
+ /* Multimode feature is not available or ADC Instance is Independent or Master,
+ or is not Slave ADC with dual regular conversions enabled.
+ Then set HAL_ADC_STATE_INJ_BUSY and reset HAL_ADC_STATE_INJ_EOC if JAUTO is set. */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO) != RESET)
+ {
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+
+ /* Enable as well injected interruptions in case
+ HAL_ADCEx_InjectedStart_IT() has not been called beforehand. This
+ allows to start regular and injected conversions when JAUTO is
+ set with a single call to HAL_ADC_Start_IT() */
+ 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;
+ }
+ } /* if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JAUTO) != RESET) */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ /* Start ADC */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADSTART);
+ }
+ else
+ {
+ /* hadc is the handle of a Slave ADC with dual regular conversions
+ enabled. Therefore, ADC_CR_ADSTART is NOT set */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ /* if Master ADC JAUTO bit is set, Slave injected interruptions
+ are enabled nevertheless (for same reason as above) */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ if (READ_BIT(tmpADC_Master->CFGR, ADC_CFGR_JAUTO) != RESET)
+ {
+ /* First, update Slave State in setting HAL_ADC_STATE_INJ_BUSY bit
+ and in resetting HAL_ADC_STATE_INJ_EOC bit */
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
+ /* Next, set Slave injected interruptions */
+ 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;
+ }
+ } /* if (READ_BIT(tmpADC_Master->CFGR, ADC_CFGR_JAUTO) != RESET) */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ } /* if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc) ) */
+ } /* if (tmp_status == HAL_OK) */
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_status;
+
+ }
+}
+
+
+
+/**
+ * @brief Stop ADC conversion of regular groups when interruptions are enabled.
+ * @note Stop as well injected conversions and disable ADC peripheral.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular and injected on-going conversions */
+ tmp_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_status == HAL_OK)
+ {
+ /* Disable all interrupts */
+ __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_EOS | ADC_IT_OVR));
+
+ /* 2. Disable the ADC peripheral */
+ tmp_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_REG_BUSY|HAL_ADC_STATE_INJ_BUSY), HAL_ADC_STATE_READY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_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.
+ * @note Case of multimode enabled (when multimode feature is available): HAL_ADC_Start_DMA()
+ * is designed for single-ADC mode only. For multimode, the dedicated
+ * HAL_ADCEx_MultiModeStart_DMA() function must be used.
+ * @param hadc: ADC handle
+ * @param pData: Destination Buffer address.
+ * @param Length: Length of data to be transferred from ADC peripheral to memory (in bytes)
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc))
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Ensure that dual regular conversions are not enabled or unavailable. */
+ /* Otherwise, dedicated API HAL_ADCEx_MultiModeStart_DMA() must be used. */
+ if (ADC_IS_DUAL_REGULAR_CONVERSION_ENABLE(hadc) == RESET)
+ {
+ /* Enable the ADC peripheral */
+ tmp_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* State machine update: Check if an injected conversion is ongoing */
+ 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
+ {
+ /* Set ADC error code to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+ }
+ /* Clear HAL_ADC_STATE_READY and regular conversion results bits, set HAL_ADC_STATE_REG_BUSY bit */
+ 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);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - by default if ADC is Master or Independent or if multimode feature is not available
+ - if multimode setting is set to independent mode (no dual regular or injected conversions are configured) */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* 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));
+
+ /* 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 */
+ SET_BIT(hadc->Instance->CFGR, ADC_CFGR_DMAEN);
+
+ /* Start the DMA channel */
+ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
+
+ /* Enable conversion of regular group. */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADSTART);
+
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ } /* if (tmp_status == HAL_OK) */
+ }
+ else
+ {
+ tmp_status = HAL_ERROR;
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ } /* if (ADC_IS_DUAL_REGULAR_CONVERSION_ENABLE(hadc) == RESET) */
+
+
+
+ /* Return function status */
+ return tmp_status;
+ } /* if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc)) */
+}
+
+
+/**
+ * @brief Stop ADC conversion of regular groups and disable ADC DMA transfer.
+ * @note Stop as well injected conversions and disable ADC peripheral.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * HAL_ADC_Stop_DMA() function is dedicated to single-ADC mode only.
+ * For multimode, the dedicated HAL_ADCEx_MultiModeStop_DMA() API must be used.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_status == HAL_OK)
+ {
+ /* 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_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_status != HAL_OK)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+ }
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* 2. Disable the ADC peripheral */
+ /* Update "tmp_status" only if DMA channel disabling passed, to keep in */
+ /* memory a potential failing status. */
+ if (tmp_status == HAL_OK)
+ {
+ tmp_status = ADC_Disable(hadc);
+ }
+ else
+ {
+ ADC_Disable(hadc);
+ }
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_REG_BUSY|HAL_ADC_STATE_INJ_BUSY), HAL_ADC_STATE_READY);
+ }
+
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+/**
+ * @brief Get ADC regular group conversion result.
+ * @param hadc: ADC handle
+ * @note Reading DR register automatically clears EOC flag. To reset EOS flag,
+ * the user must resort to the macro
+ * __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOS)
+ * @retval Converted value
+ */
+uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* 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 = 0; /* flag set if overrun occurrence has to be considered as an error */
+ ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_isr = hadc->Instance->ISR;
+ uint32_t tmp_ier = hadc->Instance->IER;
+ uint32_t tmp_cfgr = 0x0;
+ uint32_t tmp_cfgr_jqm = 0x0;
+
+
+ /* 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 regular group ===== */
+ 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 (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
+ {
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOSMP);
+ }
+
+ /* End Of Sampling callback */
+ HAL_ADCEx_EndOfSamplingCallback(hadc);
+
+ /* Clear regular group conversion flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOSMP );
+ }
+
+ /* ====== Check End of Conversion or Sequence flags for regular group ===== */
+ 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 (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
+ {
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+ }
+
+ /* Disable interruption if no further conversion upcoming by regular */
+ /* external trigger or by continuous mode, */
+ /* and if scan sequence if completed. */
+ if(ADC_IS_SOFTWARE_START_REGULAR(hadc))
+ {
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc))
+ {
+ /* check CONT bit directly in handle ADC CFGR register */
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* else need to check Master ADC CONT bit */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* Carry on if continuous mode is disabled */
+ if (READ_BIT (tmp_cfgr, ADC_CFGR_CONT) != ADC_CFGR_CONT)
+ {
+ /* 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 (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)
+ {
+ /* Disable ADC end of sequence conversion interrupt */
+ /* Note: if Overrun interrupt was enabled with EOC or EOS interrupt */
+ /* in HAL_Start_IT(), it isn't disabled here because it can be used */
+ /* by overrun IRQ process below. */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC | ADC_IT_EOS);
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+ /* If no injected conversion on-going, set HAL_ADC_STATE_READY bit */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ 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 IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+ }
+ }
+ } /* if (READ_BIT (tmp_cfgr, ADC_CFGR_CONT) != ADC_CFGR_CONT) */
+ } /* if(ADC_IS_SOFTWARE_START_REGULAR(hadc) */
+
+ /* Conversion complete callback */
+ /* Note: HAL_ADC_ConvCpltCallback can resort to
+ if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOS)) or
+ if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOC)) to determine whether
+ interruption has been triggered by end of conversion or end of
+ sequence. */
+ HAL_ADC_ConvCpltCallback(hadc);
+
+
+ /* Clear regular group conversion flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS) );
+ }
+
+
+ /* ========== Check End of Conversion flag for injected group ========== */
+ 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 (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
+ {
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+ }
+
+
+ /* Check whether interruptions can be disabled only if
+ - injected conversions are software-triggered when injected queue management is disabled
+ OR
+ - auto-injection is enabled, continuous mode is disabled (CONT = 0)
+ and regular conversions are software-triggered */
+ /* If End of Sequence is reached, disable interrupts */
+ if( __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS))
+ {
+
+ /* First, retrieve proper registers to check */
+ /* 1a. Are injected conversions that of a dual Slave ? */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEINJECTED_SLAVE(hadc))
+ {
+ /* hadc is not the handle of a Slave ADC with dual injected conversions enabled:
+ check JQM bit directly in ADC CFGR register */
+ tmp_cfgr_jqm = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* hadc is the handle of a Slave ADC with dual injected conversions enabled:
+ need to check JQM bit of Master ADC CFGR register */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ tmp_cfgr_jqm = READ_REG(tmpADC_Master->CFGR);
+ }
+ /* 1b. Is hadc the handle of a Slave ADC with regular conversions enabled? */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc))
+ {
+ /* hadc is not the handle of a Slave ADC with dual regular conversions enabled:
+ check JAUTO and CONT bits directly in ADC CFGR register */
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* hadc is not the handle of a Slave ADC with dual regular conversions enabled:
+ check JAUTO and CONT bits of Master ADC CFGR register */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+ /* Secondly, check whether JEOC and JEOS interruptions can be disabled */
+ if ((ADC_IS_SOFTWARE_START_INJECTED(hadc) && (READ_BIT(tmp_cfgr_jqm, ADC_CFGR_JQM) != ADC_CFGR_JQM))
+ && (!((READ_BIT(tmp_cfgr, (ADC_CFGR_JAUTO|ADC_CFGR_CONT)) == (ADC_CFGR_JAUTO|ADC_CFGR_CONT)) &&
+ (ADC_IS_SOFTWARE_START_REGULAR(hadc)))) )
+ {
+ /* Allowed to modify bits ADC_IT_JEOC/ADC_IT_JEOS only if bit */
+ /* JADSTART==0 (no conversion on going) */
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc) == RESET)
+ {
+ /* Disable ADC end of sequence conversion interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC | ADC_IT_JEOS);
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ /* If no regular conversion on-going, set HAL_ADC_STATE_READY bit */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ 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 IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+ }
+ }
+ } /* if( __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS)) */
+
+ /* 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. */
+ HAL_ADCEx_InjectedConvCpltCallback(hadc);
+
+ /* Clear injected group conversion flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC | ADC_FLAG_JEOS);
+ }
+
+
+ /* ========== Check Analog watchdog flags =================================================== */
+
+ /* ========== Check Analog watchdog 1 flags ========== */
+ if (((tmp_isr & ADC_FLAG_AWD1) == ADC_FLAG_AWD1) && ((tmp_ier & ADC_IT_AWD1) == ADC_IT_AWD1))
+ {
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+
+ /* Level out of window 1 callback */
+ HAL_ADC_LevelOutOfWindowCallback(hadc);
+ /* Clear ADC Analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD1);
+ }
+
+ /* ========== Check Analog watchdog 2 flags ========== */
+ if (((tmp_isr & ADC_FLAG_AWD2) == ADC_FLAG_AWD2) && ((tmp_ier & ADC_IT_AWD2) == ADC_IT_AWD2))
+ {
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+
+ /* Level out of window 2 callback */
+ HAL_ADCEx_LevelOutOfWindow2Callback(hadc);
+ /* Clear ADC Analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD2);
+ }
+
+ /* ========== Check Analog watchdog 3 flags ========== */
+ if (((tmp_isr & ADC_FLAG_AWD3) == ADC_FLAG_AWD3) && ((tmp_ier & ADC_IT_AWD3) == ADC_IT_AWD3))
+ {
+ /* Change ADC state */
+ SET_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+
+ /* Level out of window 3 callback */
+ HAL_ADCEx_LevelOutOfWindow3Callback(hadc);
+ /* 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 = 1;
+ }
+ else
+ {
+ /* check DMA configuration, depending on multimode set or not,
+ or whether or not multimode feature is available */
+ if (ADC_IS_DUAL_CONVERSION_ENABLE(hadc) == RESET)
+ {
+ /* Multimode not set or feature not available or ADC independent */
+ if (HAL_IS_BIT_SET(hadc->Instance->CFGR, ADC_CFGR_DMAEN))
+ {
+ overrun_error = 1;
+ }
+ }
+ else
+ {
+ /* Multimode (when feature is available) is enabled,
+ Common Control Register MDMA bits must be checked. */
+ if (ADC_MULTIMODE_DMA_ENABLED())
+ {
+ overrun_error = 1;
+ }
+ }
+ }
+
+ if (overrun_error == 1)
+ {
+ /* 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 */
+ HAL_ADC_ErrorCallback(hadc);
+ }
+
+ /* Clear the Overrun flag, to be done AFTER HAL_ADC_ErrorCallback() since
+ old data is preserved until OVR is reset */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+
+ }
+
+
+ /* ========== 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);
+
+ /* Error callback */
+ HAL_ADCEx_InjectedQueueOverflowCallback(hadc);
+ }
+
+}
+
+/**
+ * @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).
+ * @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 the selected channel to be linked to the regular group.
+ * @note In case of usage of internal measurement channels (Vbat / VrefInt /
+ * TempSensor), the recommended sampling time is provided by the
+ * datasheet.
+ * These internal paths can be disabled using function
+ * HAL_ADC_DeInit().
+ * @note Possibility to update parameters on the fly:
+ * HAL_ADC_ConfigChannel() initializes channel into regular group,
+ * consecutive 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.
+ * For parameters constraints, see comments of structure
+ * "ADC_ChannelConfTypeDef".
+ * @param hadc: ADC handle
+ * @param sConfig: Structure ADC channel for regular group.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ ADC_Common_TypeDef *tmpADC_Common;
+ uint32_t tmpOffsetShifted;
+ __IO uint32_t wait_loop_index = 0;
+
+ /* 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 (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)
+ {
+
+ /* Regular sequence configuration */
+ /* Clear the old SQx bits then set the new ones for the selected rank */
+ /* For Rank 1 to 4 */
+ if (sConfig->Rank < 5)
+ {
+ MODIFY_REG(hadc->Instance->SQR1,
+ ADC_SQR1_RK(ADC_SQR2_SQ5, sConfig->Rank),
+ ADC_SQR1_RK(sConfig->Channel, sConfig->Rank));
+ }
+ /* For Rank 5 to 9 */
+ else if (sConfig->Rank < 10)
+ {
+ MODIFY_REG(hadc->Instance->SQR2,
+ ADC_SQR2_RK(ADC_SQR2_SQ5, sConfig->Rank),
+ ADC_SQR2_RK(sConfig->Channel, sConfig->Rank));
+ }
+ /* For Rank 10 to 14 */
+ else if (sConfig->Rank < 15)
+ {
+ MODIFY_REG(hadc->Instance->SQR3,
+ ADC_SQR3_RK(ADC_SQR3_SQ10, sConfig->Rank),
+ ADC_SQR3_RK(sConfig->Channel, sConfig->Rank));
+ }
+ /* For Rank 15 to 16 */
+ else
+ {
+ MODIFY_REG(hadc->Instance->SQR4,
+ ADC_SQR4_RK(ADC_SQR4_SQ15, sConfig->Rank),
+ ADC_SQR4_RK(sConfig->Channel, sConfig->Rank));
+ }
+
+
+ /* 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 (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET)
+ {
+
+ /* Channel sampling time configuration */
+ /* Clear the old sample time then set the new one for the selected channel */
+ /* For channels 10 to 18 */
+ if (sConfig->Channel >= ADC_CHANNEL_10)
+ {
+ ADC_SMPR2_SETTING(hadc, sConfig->SamplingTime, sConfig->Channel);
+ }
+ else /* For channels 0 to 9 */
+ {
+ ADC_SMPR1_SETTING(hadc, sConfig->SamplingTime, sConfig->Channel);
+ }
+
+
+ /* 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, sConfig->Offset);
+
+ switch (sConfig->OffsetNumber)
+ {
+ /* Configure offset register i when applicable: */
+ /* - Enable offset */
+ /* - Set channel number */
+ /* - Set offset value */
+ case ADC_OFFSET_1:
+ MODIFY_REG(hadc->Instance->OFR1,
+ ADC_OFR_FIELDS,
+ ADC_OFR1_OFFSET1_EN | ADC_OFR_CHANNEL(sConfig->Channel) | tmpOffsetShifted);
+ break;
+
+ case ADC_OFFSET_2:
+ MODIFY_REG(hadc->Instance->OFR2,
+ ADC_OFR_FIELDS,
+ ADC_OFR2_OFFSET2_EN | ADC_OFR_CHANNEL(sConfig->Channel) | tmpOffsetShifted);
+ break;
+
+ case ADC_OFFSET_3:
+ MODIFY_REG(hadc->Instance->OFR3,
+ ADC_OFR_FIELDS,
+ ADC_OFR3_OFFSET3_EN | ADC_OFR_CHANNEL(sConfig->Channel) | tmpOffsetShifted);
+ break;
+
+ case ADC_OFFSET_4:
+ MODIFY_REG(hadc->Instance->OFR4,
+ ADC_OFR_FIELDS,
+ ADC_OFR4_OFFSET4_EN | ADC_OFR_CHANNEL(sConfig->Channel) | tmpOffsetShifted);
+ break;
+
+ /* Case ADC_OFFSET_NONE */
+ default :
+ /* Scan OFR1, OFR2, OFR3, OFR4 to check if the selected channel is enabled.
+ If this is the case, offset OFRx is disabled since
+ sConfig->OffsetNumber = ADC_OFFSET_NONE. */
+ if (((hadc->Instance->OFR1) & ADC_OFR1_OFFSET1_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR1, ADC_OFR1_OFFSET1_EN);
+ }
+ if (((hadc->Instance->OFR2) & ADC_OFR2_OFFSET2_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR2, ADC_OFR2_OFFSET2_EN);
+ }
+ if (((hadc->Instance->OFR3) & ADC_OFR3_OFFSET3_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR3, ADC_OFR3_OFFSET3_EN);
+ }
+ if (((hadc->Instance->OFR4) & ADC_OFR4_OFFSET4_CH) == ADC_OFR_CHANNEL(sConfig->Channel))
+ {
+ CLEAR_BIT(hadc->Instance->OFR4, ADC_OFR4_OFFSET4_EN);
+ }
+ break;
+ } /* switch (sConfig->OffsetNumber) */
+
+ } /* if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET) */
+
+
+
+ /* 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 (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ /* Configuration of differential mode */
+ if (sConfig->SingleDiff != ADC_DIFFERENTIAL_ENDED)
+ {
+ /* Disable differential mode (default mode: single-ended) */
+ CLEAR_BIT(hadc->Instance->DIFSEL, ADC_DIFSEL_CHANNEL(sConfig->Channel));
+ }
+ else
+ {
+ /* Enable differential mode */
+ SET_BIT(hadc->Instance->DIFSEL, ADC_DIFSEL_CHANNEL(sConfig->Channel));
+
+ /* Sampling time configuration of channel ADC_IN+1 (negative input) */
+ /* Clear the old sample time then set the new one for the selected */
+ /* channel. */
+ /* Starting from channel 9, SMPR2 register must be configured */
+ if (sConfig->Channel >= ADC_CHANNEL_9)
+ {
+ ADC_SMPR2_SETTING(hadc, sConfig->SamplingTime, sConfig->Channel+1);
+ }
+ else /* For channels 0 to 8, SMPR1 must be configured */
+ {
+ ADC_SMPR1_SETTING(hadc, sConfig->SamplingTime, sConfig->Channel+1);
+ }
+ }
+
+
+
+ /* 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(). */
+
+ /* Configuration of common ADC parameters */
+ tmpADC_Common = ADC_COMMON_REGISTER(hadc);
+
+
+ /* If the requested internal measurement path has already been enabled, */
+ /* bypass the configuration processing. */
+ if (( (sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) &&
+ (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_TSEN)) ) ||
+ ( (sConfig->Channel == ADC_CHANNEL_VBAT) &&
+ (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VBATEN)) ) ||
+ ( (sConfig->Channel == ADC_CHANNEL_VREFINT) &&
+ (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VREFEN)))
+ )
+ {
+ /* Configuration of common ADC parameters (continuation) */
+
+ /* Software is allowed to change common parameters only when all ADCs */
+ /* of the common group are disabled. */
+ if ((ADC_IS_ENABLE(hadc) == RESET) &&
+ (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )
+ {
+ if (sConfig->Channel == ADC_CHANNEL_TEMPSENSOR)
+ {
+ if (ADC_TEMPERATURE_SENSOR_INSTANCE(hadc))
+ {
+ SET_BIT(tmpADC_Common->CCR, ADC_CCR_TSEN);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000));
+ while(wait_loop_index != 0)
+ {
+ wait_loop_index--;
+ }
+ }
+ }
+ else if (sConfig->Channel == ADC_CHANNEL_VBAT)
+ {
+ if (ADC_BATTERY_VOLTAGE_INSTANCE(hadc))
+ {
+ SET_BIT(tmpADC_Common->CCR, ADC_CCR_VBATEN);
+ }
+ }
+ else if (sConfig->Channel == ADC_CHANNEL_VREFINT)
+ {
+ if (ADC_VREFINT_INSTANCE(hadc))
+ {
+ SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);
+ }
+ }
+ }
+ /* 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_status = HAL_ERROR;
+ }
+ }
+
+ } /* if (ADC_IS_ENABLE(hadc) == RESET) */
+
+ } /* if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET) */
+
+ /* 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_status = HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_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, e.g. to set several channels to monitor simultaneously.
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_AnalogWDGConfTypeDef".
+ * @param hadc: ADC handle
+ * @param AnalogWDGConfig: Structure of ADC analog watchdog configuration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef* hadc, ADC_AnalogWDGConfTypeDef* AnalogWDGConfig)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+
+ uint32_t tmpAWDHighThresholdShifted;
+ uint32_t tmpAWDLowThresholdShifted;
+
+ uint32_t tmpADCFlagAWD2orAWD3;
+ uint32_t tmpADCITAWD2orAWD3;
+
+ /* 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((AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REG) ||
+ (AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_INJEC) ||
+ (AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REGINJEC) )
+ {
+ assert_param(IS_ADC_CHANNEL(hadc, AnalogWDGConfig->Channel));
+ }
+
+
+ /* Verify if threshold is 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));
+
+ /* 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 and injected groups: */
+ /* - Analog watchdog channels */
+ /* - Analog watchdog thresholds */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET)
+ {
+
+ /* Analog watchdogs configuration */
+ if(AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_1)
+ {
+ /* Configuration of analog watchdog: */
+ /* - Set the analog watchdog enable mode: regular and/or injected */
+ /* groups, one or overall group of channels. */
+ /* - Set the Analog watchdog channel (is not used if watchdog */
+ /* mode "all channels": ADC_CFGR_AWD1SGL=0). */
+
+ MODIFY_REG(hadc->Instance->CFGR, ADC_CFGR_WD_FIELDS,
+ AnalogWDGConfig->WatchdogMode | ADC_CFGR_SET_AWD1CH(AnalogWDGConfig->Channel) );
+
+ /* Shift the offset with respect to 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 the high and low thresholds */
+ MODIFY_REG(hadc->Instance->TR1, ADC_TR1_HT1 | ADC_TR1_LT1,
+ ADC_TRX_HIGHTHRESHOLD (tmpAWDHighThresholdShifted) | tmpAWDLowThresholdShifted );
+
+ /* Clear the ADC Analog watchdog flag (in case left enabled by */
+ /* previous ADC operations) to be ready to use for HAL_ADC_IRQHandler() */
+ /* or HAL_ADC_PollForEvent(). */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_IT_AWD1);
+
+ /* Configure ADC Analog watchdog interrupt */
+ if(AnalogWDGConfig->ITMode == ENABLE)
+ {
+ /* Enable the ADC Analog watchdog interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_AWD1);
+ }
+ else
+ {
+ /* Disable the ADC Analog watchdog interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD1);
+ }
+
+ /* Update state, clear previous result related to AWD1 */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD1);
+ }
+ /* Case of ADC_ANALOGWATCHDOG_2 and ADC_ANALOGWATCHDOG_3 */
+ else
+ {
+ /* Shift the threshold with respect to 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);
+
+ if (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_2)
+ {
+ /* Set the Analog watchdog channel or group of channels. This also */
+ /* enables the watchdog. */
+ /* Note: Conditional register reset, because several channels can be */
+ /* set by successive calls of this function. */
+ if (AnalogWDGConfig->WatchdogMode != ADC_ANALOGWATCHDOG_NONE)
+ {
+ SET_BIT(hadc->Instance->AWD2CR, ADC_CFGR_SET_AWD23CR(AnalogWDGConfig->Channel));
+ }
+ else
+ {
+ CLEAR_BIT(hadc->Instance->AWD2CR, ADC_AWD2CR_AWD2CH);
+ }
+
+ /* Set the high and low thresholds */
+ MODIFY_REG(hadc->Instance->TR2, ADC_TR2_HT2 | ADC_TR2_LT2,
+ ADC_TRX_HIGHTHRESHOLD (tmpAWDHighThresholdShifted) | tmpAWDLowThresholdShifted );
+
+ /* Set temporary variable to flag and IT of AWD2 or AWD3 for further */
+ /* settings. */
+ tmpADCFlagAWD2orAWD3 = ADC_FLAG_AWD2;
+ tmpADCITAWD2orAWD3 = ADC_IT_AWD2;
+
+ /* Update state, clear previous result related to AWD2 */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD2);
+ }
+ /* (AnalogWDGConfig->WatchdogNumber == ADC_ANALOGWATCHDOG_3) */
+ else
+ {
+ /* Set the Analog watchdog channel or group of channels. This also */
+ /* enables the watchdog. */
+ /* Note: Conditional register reset, because several channels can be */
+ /* set by successive calls of this function. */
+ if (AnalogWDGConfig->WatchdogMode != ADC_ANALOGWATCHDOG_NONE)
+ {
+ SET_BIT(hadc->Instance->AWD3CR, ADC_CFGR_SET_AWD23CR(AnalogWDGConfig->Channel));
+ }
+ else
+ {
+ CLEAR_BIT(hadc->Instance->AWD3CR, ADC_AWD3CR_AWD3CH);
+ }
+
+ /* Set the high and low thresholds */
+ MODIFY_REG(hadc->Instance->TR3, ADC_TR3_HT3 | ADC_TR3_LT3,
+ ADC_TRX_HIGHTHRESHOLD (tmpAWDHighThresholdShifted) | tmpAWDLowThresholdShifted );
+
+ /* Set temporary variable to flag and IT of AWD2 or AWD3 for further */
+ /* settings. */
+ tmpADCFlagAWD2orAWD3 = ADC_FLAG_AWD3;
+ tmpADCITAWD2orAWD3 = ADC_IT_AWD3;
+
+ /* Update state, clear previous result related to AWD3 */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_AWD3);
+ }
+
+ /* Clear the ADC Analog watchdog flag (in case left enabled by */
+ /* previous ADC operations) to be ready to use for HAL_ADC_IRQHandler() */
+ /* or HAL_ADC_PollForEvent(). */
+ __HAL_ADC_CLEAR_FLAG(hadc, tmpADCFlagAWD2orAWD3);
+
+ /* Configure ADC Analog watchdog interrupt */
+ if(AnalogWDGConfig->ITMode == ENABLE)
+ {
+ __HAL_ADC_ENABLE_IT(hadc, tmpADCITAWD2orAWD3);
+ }
+ else
+ {
+ __HAL_ADC_DISABLE_IT(hadc, tmpADCITAWD2orAWD3);
+ }
+ }
+
+ }
+ /* If a conversion is on going on regular or injected groups, 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_status = HAL_ERROR;
+ }
+
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+
+ /* Return function status */
+ return tmp_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.
+ * @param hadc: ADC handle
+ * @retval HAL state (uint32_t bit-map)
+ */
+uint32_t HAL_ADC_GetState(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 (uint32_t bit-map)
+ */
+uint32_t HAL_ADC_GetError(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 ADC injected conversion type.
+ * @arg @ref ADC_REGULAR_INJECTED_GROUP ADC regular and injected conversion type.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef ADC_ConversionStop(ADC_HandleTypeDef* hadc, uint32_t ConversionGroup)
+{
+ uint32_t tmp_ADC_CR_ADSTART_JADSTART = 0;
+ uint32_t tickstart = 0;
+ uint32_t Conversion_Timeout_CPU_cycles = 0;
+
+ /* 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. */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc))
+ {
+ /* 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 ((HAL_IS_BIT_SET(hadc->Instance->CFGR, ADC_CFGR_JAUTO))
+ && (hadc->Init.ContinuousConvMode==ENABLE)
+ && (hadc->Init.LowPowerAutoWait==ENABLE))
+ {
+ /* Use stop of regular group */
+ ConversionGroup = ADC_REGULAR_GROUP;
+
+ /* Wait until JEOS=1 (maximum Timeout: 4 injected conversions) */
+ while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOS) == RESET)
+ {
+ if (Conversion_Timeout_CPU_cycles >= (ADC_CONVERSION_TIME_MAX_CPU_CYCLES *4))
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP 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 regular group */
+ if (ConversionGroup != ADC_INJECTED_GROUP)
+ {
+ /* Software is allowed to set ADSTP only when ADSTART=1 and ADDIS=0 */
+ if (HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADSTART) &&
+ HAL_IS_BIT_CLR(hadc->Instance->CR, ADC_CR_ADDIS) )
+ {
+ /* Stop conversions on regular group */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADSTP);
+ }
+ }
+
+ /* Stop potential conversion on going on injected group */
+ if (ConversionGroup != ADC_REGULAR_GROUP)
+ {
+ /* Software is allowed to set JADSTP only when JADSTART=1 and ADDIS=0 */
+ if (HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_JADSTART) &&
+ HAL_IS_BIT_CLR(hadc->Instance->CR, ADC_CR_ADDIS) )
+ {
+ /* Stop conversions on injected group */
+ SET_BIT(hadc->Instance->CR, ADC_CR_JADSTP);
+ }
+ }
+
+ /* Selection of start and stop bits with respect to the regular or injected group */
+ switch(ConversionGroup)
+ {
+ 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) != RESET)
+ {
+ 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 IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+ }
+
+ } /* if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc)) */
+
+ /* 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 = 0;
+
+ /* ADC enable and wait for ADC ready (in case of ADC is disabled or */
+ /* enabling phase not yet completed: flag ADC ready not set yet). */
+ /* Timeout implemented not to be stuck if ADC cannot be enabled (possible */
+ /* causes: ADC clock not running, ...). */
+ if (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ /* Check if conditions to enable the ADC are fulfilled */
+ if (ADC_ENABLING_CONDITIONS(hadc) == RESET)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the ADC peripheral */
+ ADC_ENABLE(hadc);
+
+
+ /* Wait for ADC effectively enabled */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == RESET)
+ {
+ /* 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 */
+ ADC_ENABLE(hadc);
+
+ 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 IP 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 = 0;
+
+ /* Verification if ADC is not already disabled: */
+ /* Note: forbidden to disable ADC (set bit ADC_CR_ADDIS) if ADC is already */
+ /* disabled. */
+ if (ADC_IS_ENABLE(hadc) != RESET )
+ {
+ /* Check if conditions to disable the ADC are fulfilled */
+ if (ADC_DISABLING_CONDITIONS(hadc) != RESET)
+ {
+ /* Disable the ADC peripheral */
+ ADC_DISABLE(hadc);
+ }
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP internal error */
+ SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
+
+ return HAL_ERROR;
+ }
+
+ /* Wait for ADC effectively disabled */
+ tickstart = HAL_GetTick();
+
+ while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADEN))
+ {
+ if((HAL_GetTick()-tickstart) > ADC_DISABLE_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Set ADC error code to ADC IP 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 (HAL_IS_BIT_CLR(hadc->State, (HAL_ADC_STATE_ERROR_INTERNAL|HAL_ADC_STATE_ERROR_DMA)))
+ {
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
+ /* Is it the end of the regular sequence ? */
+ if (HAL_IS_BIT_SET(hadc->Instance->ISR, ADC_FLAG_EOS))
+ {
+ /* Are conversions software-triggered ? */
+ if(ADC_IS_SOFTWARE_START_REGULAR(hadc))
+ {
+ /* Is CONT bit set ? */
+ if (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_CONT) == RESET)
+ {
+ /* CONT bit is not set, no more conversions expected */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ 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) == RESET)
+ {
+ /* DMACFG bit is not set, conversions are stopped. */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ }
+
+ /* Conversion complete callback */
+ HAL_ADC_ConvCpltCallback(hadc);
+ }
+ else /* DMA or internal error occurred (or both) */
+ {
+ /* In case of internal error, */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
+ {
+ /* call Error Callback function */
+ HAL_ADC_ErrorCallback(hadc);
+ }
+
+ }
+
+
+}
+
+/**
+ * @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 */
+ HAL_ADC_ConvHalfCpltCallback(hadc);
+}
+
+/**
+ * @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;
+
+ /* Change 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 */
+ HAL_ADC_ErrorCallback(hadc);
+}
+
+
+/**
+ * @}
+ */
+
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_adc_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_adc_ex.c
new file mode 100644
index 000000000..96c8b517a
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_adc_ex.c
@@ -0,0 +1,2382 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_adc_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC)
+ * peripheral:
+ * + Calibration functions
+ * ++ Calibration start-up
+ * ++ Calibration value reading or setting
+ * + Operation functions
+ * ++ Start, stop, get result of conversions of injected
+ * groups, using 3 possible modes: polling or interruption.
+ * ++ Multimode feature when available
+ * + Control functions
+ * ++ Configure channels on injected group
+ * + State functions
+ * ++ Injected group queues management
+ *
+ @verbatim
+ ==============================================================================
+ ##### ADC specific features #####
+ ==============================================================================
+ [..]
+ (#) Interrupt generation at the end of injected conversion and in case of
+ injected queues overflow.
+
+ (#) External trigger (timer or EXTI) with configurable polarity for
+ injected groups.
+
+ (#) Multimode Dual mode when multimode feature is available.
+
+ (#) Configurable DMA data storage in Multimode Dual mode.
+
+ (#) Configurable delay between conversions in Dual interleaved mode.
+
+ (#) ADC calibration.
+
+ (#) ADC channels selectable single/differential input.
+
+ (#) ADC Injected sequencer&channels configuration context queue.
+
+ (#) ADC offset on injected groups.
+
+ (#) ADC oversampling.
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+
+ (#) Configure the ADC parameters (conversion resolution, data alignment,
+ continuous mode, ...) using the HAL_ADC_Init() function.
+
+ (#) Activate the ADC peripheral using one of the start functions:
+ HAL_ADCEx_InjectedStart(), HAL_ADCEx_InjectedStart_IT() for injected conversions
+ or
+ HAL_ADC_MultiModeStart_DMA() for multimode conversions when multimode
+ feature is available.
+
+
+ *** Channels to injected group configuration ***
+ =============================================
+ [..]
+ (+) To configure the ADC Injected channels group features, use
+ HAL_ADCEx_InjectedConfigChannel() functions.
+ (+) To read the ADC converted values, use the HAL_ADCEx_InjectedGetValue()
+ function.
+
+
+ *** Multimode ADCs configuration (when multimode feature is available) ***
+ ========================================================================
+ [..]
+ (+) Multimode feature is available and applicable to Master and
+ Slave ADCs.
+ (+) Refer to "Channels to regular group configuration" description to
+ configure the Master and Slave regular groups.
+ (+) Select the Multi mode ADC features (dual mode
+ simultaneous, interleaved, ...) and configure the DMA mode using
+ HAL_ADCEx_MultiModeConfigChannel() functions.
+ (+) Read the ADCs converted values using the HAL_ADCEx_MultiModeGetValue()
+ function.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_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 ((uint32_t)(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 */
+
+#define ADC_CFGR2_INJ_FIELDS ((uint32_t)(ADC_CFGR2_JOVSE | ADC_CFGR2_OVSR |\
+ ADC_CFGR2_OVSS )) /*!< ADC_CFGR2 injected oversampling parameters that can be updated
+ when no conversion is on-going (neither regular nor injected) */
+
+/* Fixed timeout value for ADC calibration. */
+/* Values defined to be higher than worst cases: low clock frequency, */
+/* maximum prescalers. */
+/* Ex of profile low frequency : f_ADC at 0.14 MHz (minimum value */
+/* according to Data sheet), calibration_time MAX = 112 / f_ADC */
+/* 112 / 140,000 = 0.8 ms */
+/* At maximum CPU speed (80 MHz), this means */
+/* 0.8 ms * 80 MHz = 64000 CPU cycles */
+#define ADC_CALIBRATION_TIMEOUT ((uint32_t) 64000) /*!< ADC calibration time-out value */
+
+/**
+ * @}
+ */
+
+/* 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 injected group.
+ (+) Stop conversion of injected group.
+ (+) Poll for conversion complete on injected group.
+ (+) Get result of injected channel conversion.
+ (+) Start conversion of injected group and enable interruptions.
+ (+) Stop conversion of injected group and disable interruptions.
+
+ (+) When multimode feature is available, start multimode and enable DMA transfer.
+ (+) Stop multimode and disable ADC DMA transfer.
+ (+) Get result of multimode conversion.
+
+
+
+@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
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t SingleDiff)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+ uint32_t WaitLoopIndex = 0;
+
+ /* 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_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_BUSY_INTERNAL bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_REG_BUSY|HAL_ADC_STATE_INJ_BUSY), HAL_ADC_STATE_BUSY_INTERNAL);
+
+ /* Select calibration mode single ended or differential ended */
+ MODIFY_REG(hadc->Instance->CR, ADC_CR_ADCALDIF, SingleDiff);
+
+ /* Start ADC calibration */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADCAL);
+
+
+ /* Wait for calibration completion */
+ while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL))
+ {
+ WaitLoopIndex++;
+ if (WaitLoopIndex >= ADC_CALIBRATION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ /* Clear HAL_ADC_STATE_BUSY_INTERNAL bit, set HAL_ADC_STATE_ERROR_INTERNAL bit */
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* 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);
+ }
+ else
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Update ADC state machine to error */
+ tmp_status = HAL_ERROR;
+ }
+
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+
+
+/**
+ * @brief Get the calibration factor from automatic conversion result.
+ * @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
+ * @retval Converted value
+ */
+uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff)
+{
+ /* 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 (SingleDiff == ADC_DIFFERENTIAL_ENDED)
+ {
+ return ADC_CALFACT_DIFF_GET(hadc->Instance->CALFACT);
+ }
+ else
+ {
+ return ((hadc->Instance->CALFACT) & ADC_CALFACT_CALFACT_S);
+ }
+}
+
+
+
+/**
+ * @brief Set the calibration factor to overwrite automatic conversion result. ADC must be enabled and no conversion on going.
+ * @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
+ * @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)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* 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. */
+ if ( (ADC_IS_ENABLE(hadc) != RESET) &&
+ (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET) )
+ {
+ /* Set the selected ADC calibration value */
+ if (SingleDiff == ADC_DIFFERENTIAL_ENDED)
+ {
+ MODIFY_REG(hadc->Instance->CALFACT, ADC_CALFACT_CALFACT_D, ADC_CALFACT_DIFF_SET(CalibrationFactor));
+ }
+ else
+ {
+ MODIFY_REG(hadc->Instance->CALFACT, ADC_CALFACT_CALFACT_S, CalibrationFactor);
+ }
+ }
+ else
+ {
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Update ADC state machine to error */
+ tmp_status = HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+
+/**
+ * @brief Enable ADC, start conversion of injected group.
+ * @note Interruptions enabled in this function: None.
+ * @note Case of multimode enabled when multimode feature is available:
+ * HAL_ADCEx_InjectedStart() API must be called for ADC slave first,
+ * then for ADC master.
+ * For ADC slave, ADC is enabled only (conversion is not started).
+ * For ADC master, ADC is enabled and multimode conversion is started.
+ * @param hadc: ADC handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc))
+ {
+ 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 */
+ if ((READ_BIT(hadc->Instance->JSQR, ADC_JSQR_JEXTEN) == RESET)
+ && (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS) == RESET))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Check if a regular conversion is ongoing */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ /* 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);
+ }
+ /* Update ADC state */
+ /* Clear HAL_ADC_STATE_READY and HAL_ADC_STATE_INJ_EOC bits, set HAL_ADC_STATE_INJ_BUSY bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_READY|HAL_ADC_STATE_INJ_EOC), HAL_ADC_STATE_INJ_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - by default if ADC is Master or Independent or if multimode feature is not available
+ - if multimode setting is set to independent mode (no dual regular or injected conversions are configured) */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+
+ /* Clear 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));
+
+ /* 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. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* if ADC is slave, */
+ /* - ADC is enabled only (conversion is not started). */
+ /* - if multimode only concerns regular conversion, ADC is enabled */
+ /* and conversion is started. */
+ /* If ADC is master or independent, */
+ /* - ADC is enabled and conversion is started. */
+
+ /* Are injected conversions that of a dual Slave ? */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEINJECTED_SLAVE(hadc))
+ {
+ /* hadc is not the handle of a Slave ADC with dual injected conversions enabled:
+ set ADSTART only if JAUTO is cleared */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ if (HAL_IS_BIT_CLR(hadc->Instance->CFGR, ADC_CFGR_JAUTO))
+ {
+ SET_BIT(hadc->Instance->CR, ADC_CR_JADSTART) ;
+ }
+ }
+ else
+ {
+ /* hadc is the handle of a Slave ADC with dual injected conversions enabled:
+ ADSTART is not set */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ } /* if (tmp_status == HAL_OK) */
+
+
+ /* Return function status */
+ return tmp_status;
+ } /* if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc)) */
+}
+
+
+
+/**
+ * @brief Stop conversion of injected channels, disable ADC peripheral if no regular conversion is on going.
+ * @note If ADC must be disabled and if regular conversion
+ * is on going, function HAL_ADC_Stop() must be used.
+ * @note In case of auto-injection mode, HAL_ADC_Stop() must be used.
+ * @note In case of multimode enabled (when multimode feature is available),
+ * HAL_ADCEx_InjectedStop() must be called for ADC master first, then for ADC slave.
+ * For ADC master, conversion is stopped and ADC is disabled.
+ * For ADC slave, ADC is disabled only (conversion stop of ADC master
+ * has already stopped conversion of ADC slave).
+ * @param hadc: ADC handle.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* 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_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_status == HAL_OK)
+ {
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_READY bit */
+ 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
+ {
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_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 = 0x00;
+ ADC_TypeDef *tmpADC_Master;
+ uint32_t tmp_cfgr = 0x00;
+ uint32_t tmp_cfgr_jqm_autdly = 0x00;
+ uint32_t tmp_jeos_raised = 0x01; /* by default, assume that JEOS is set,
+ tmp_jeos_raised will be corrected
+ accordingly during API execution */
+
+ /* 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(HAL_IS_BIT_CLR(hadc->Instance->ISR, tmp_Flag_End))
+ {
+ /* Check if timeout is disabled (set to infinite wait) */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ /* Update ADC state machine to timeout */
+ SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Next, to clear the polled flag as well as to update the handle State,
+ JEOS is checked and the relevant configuration registers are retrieved.
+ JQM, JAUTO and CONT bits will have to be read for the State update,
+ AUTDLY for JEOS clearing. */
+ /* 1. Check whether or not JEOS is set */
+ if (HAL_IS_BIT_CLR(hadc->Instance->ISR, ADC_FLAG_JEOS))
+ {
+ tmp_jeos_raised = 0;
+ }
+ /* 2. Check whether or not hadc is the handle of a Slave ADC with dual
+ injected conversions enabled. */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEINJECTED_SLAVE(hadc) == RESET)
+ {
+ /* hadc is not the handle of a Slave ADC with dual injected conversions enabled:
+ check JQM and AUTDLY bits directly in ADC CFGR register */
+ tmp_cfgr_jqm_autdly = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* hadc is the handle of a Slave ADC with dual injected conversions enabled:
+ need to check JQM and AUTDLY bits of Master ADC CFGR register */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ tmp_cfgr_jqm_autdly = READ_REG(tmpADC_Master->CFGR);
+ }
+ /* 3. Check whether or not hadc is the handle of a Slave ADC with dual
+ regular conversions enabled. */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEREGULAR_SLAVE(hadc))
+ {
+ /* hadc is not the handle of a Slave ADC with dual regular conversions enabled:
+ check JAUTO and CONT bits directly in ADC CFGR register */
+ tmp_cfgr = READ_REG(hadc->Instance->CFGR);
+ }
+ else
+ {
+ /* hadc is not the handle of a Slave ADC with dual regular conversions enabled:
+ check JAUTO and CONT bits of Master ADC CFGR register */
+ tmpADC_Master = ADC_MASTER_REGISTER(hadc);
+ tmp_cfgr = READ_REG(tmpADC_Master->CFGR);
+ }
+
+
+
+ /* 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. */
+ /* Note that 1. reading ADCx_JDRy clears JEOC. */
+ /* 2. in multimode with dual injected conversions enabled (when */
+ /* multimode feature is available), Master AUTDLY bit is */
+ /* checked. */
+ if (READ_BIT (tmp_cfgr_jqm_autdly, ADC_CFGR_AUTDLY) == RESET)
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
+ }
+ }
+ else
+ {
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
+ }
+
+
+ /* Update ADC state machine */
+ SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
+ /* Are injected conversions over ? This is the case if JEOS is set AND
+ - injected conversions are software-triggered when injected queue management is disabled
+ OR
+ - auto-injection is enabled, continuous mode is disabled,
+ and regular conversions are software-triggered */
+
+ if (tmp_jeos_raised)
+ {
+ if ((ADC_IS_SOFTWARE_START_INJECTED(hadc) && (READ_BIT(tmp_cfgr_jqm_autdly, ADC_CFGR_JQM) != ADC_CFGR_JQM))
+ && (!((READ_BIT(tmp_cfgr, (ADC_CFGR_JAUTO|ADC_CFGR_CONT)) == (ADC_CFGR_JAUTO|ADC_CFGR_CONT)) &&
+ (ADC_IS_SOFTWARE_START_REGULAR(hadc))) ))
+ {
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ /* If no regular conversion on-going, set HAL_ADC_STATE_READY bit */
+ if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_READY);
+ }
+ }
+ }
+
+
+
+ /* 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)
+ * @note Case of multimode enabled (when multimode feature is enabled):
+ * HAL_ADCEx_InjectedStart_IT() API must be called for ADC slave first,
+ * then for ADC master.
+ * For ADC slave, ADC is enabled only (conversion is not started).
+ * For ADC master, ADC is enabled and multimode conversion is started.
+ * @param hadc: ADC handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc))
+ {
+ 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 */
+ if ((READ_BIT(hadc->Instance->JSQR, ADC_JSQR_JEXTEN) == RESET)
+ && (READ_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS) == RESET))
+ {
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the ADC peripheral */
+ tmp_status = ADC_Enable(hadc);
+
+ /* Start conversion if ADC is effectively enabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Check if a regular conversion is ongoing */
+ if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_REG_BUSY))
+ {
+ /* 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);
+ }
+ /* Clear HAL_ADC_STATE_READY and HAL_ADC_STATE_INJ_EOC bits, set HAL_ADC_STATE_INJ_BUSY bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_READY|HAL_ADC_STATE_INJ_EOC), HAL_ADC_STATE_INJ_BUSY);
+
+ /* Reset HAL_ADC_STATE_MULTIMODE_SLAVE bit
+ - by default if ADC is Master or Independent or if multimode feature is not available
+ - if multimode setting is set to independent mode (no dual regular or injected conversions are configured) */
+ if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
+ {
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ }
+
+ /* Clear 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));
+
+ /* Enable ADC Injected context queue overflow interrupt if this feature */
+ /* is enabled. */
+ if ((hadc->Instance->CFGR & ADC_CFGR_JQM) != RESET)
+ {
+ __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. */
+ /* Case of multimode enabled (when multimode feature is available): */
+ /* if ADC is slave, */
+ /* - ADC is enabled only (conversion is not started), */
+ /* - if multimode only concerns regular conversion, ADC is enabled */
+ /* and conversion is started. */
+ /* If ADC is master or independent, */
+ /* - ADC is enabled and conversion is started. */
+
+ /* Are injected conversions that of a dual Slave ? */
+ if (ADC_INDEPENDENT_OR_NONMULTIMODEINJECTED_SLAVE(hadc))
+ {
+ /* hadc is not the handle of a Slave ADC with dual injected conversions enabled:
+ set ADSTART only if JAUTO is cleared */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ if (HAL_IS_BIT_CLR(hadc->Instance->CFGR, ADC_CFGR_JAUTO))
+ {
+ SET_BIT(hadc->Instance->CR, ADC_CR_JADSTART) ;
+ }
+ }
+ else
+ {
+ /* hadc is the handle of a Slave ADC with dual injected conversions enabled:
+ ADSTART is not set */
+ SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_status;
+}
+}
+
+
+
+/**
+ * @brief Stop conversion of injected channels, disable interruption of end-of-conversion.
+ * @note Disable ADC peripheral if no regular conversion
+ * is on going.
+ * @note If ADC must be disabled and if regular conversion
+ * is on going, function HAL_ADC_Stop must be used first.
+ * @note Case of multimode enabled (when multimode feature is available):
+ * HAL_ADCEx_InjectedStop_IT() API must be called for ADC master first,
+ * then for ADC slave.
+ * For ADC master, conversion is stopped and ADC is disabled.
+ * For ADC slave, ADC is disabled only (conversion stop of ADC master
+ * has already stopped conversion of ADC slave).
+ * @note In case of auto-injection mode, HAL_ADC_Stop() must be used.
+ * @param hadc: ADC handle
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* 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_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_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 ((ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET))
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_READY bit */
+ 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
+ {
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+/**
+ * @brief Enable ADC, start MultiMode conversion and transfer regular results through DMA.
+ * @note Multimode must have been previously configured using
+ * HAL_ADCEx_MultiModeConfigChannel() function.
+ * Interruptions enabled in this function:
+ * overrun, DMA half transfer, DMA transfer complete.
+ * Each of these interruptions has its dedicated callback function.
+ * @note State field of Slave ADC handle is not updated in this configuration:
+ * user should not rely on it for information related to Slave regular
+ * conversions.
+ * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
+ * @param pData: Destination Buffer address.
+ * @param Length: Length of data to be transferred from ADC peripheral to memory (in bytes).
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+ ADC_HandleTypeDef tmphadcSlave;
+ ADC_Common_TypeDef *tmpADC_Common;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXTTRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests));
+
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc))
+ {
+ return HAL_BUSY;
+ }
+ else
+ {
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+
+ /* Enable the ADC peripherals: master and slave (in case if not already */
+ /* enabled previously) */
+ tmp_status = ADC_Enable(hadc);
+ if (tmp_status == HAL_OK)
+ {
+ tmp_status = ADC_Enable(&tmphadcSlave);
+ }
+
+ /* Start multimode conversion of ADCs pair */
+ if (tmp_status == HAL_OK)
+ {
+ /* Update Master State */
+ /* Clear HAL_ADC_STATE_READY and regular conversion results bits, set HAL_ADC_STATE_REG_BUSY bit */
+ 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 to none */
+ ADC_CLEAR_ERRORCODE(hadc);
+
+
+ /* 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 ;
+
+ /* Pointer to the common control register */
+ tmpADC_Common = ADC_COMMON_REGISTER(hadc);
+
+
+ /* 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));
+
+ /* Enable ADC overrun interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Start the DMA channel */
+ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&tmpADC_Common->CDR, (uint32_t)pData, Length);
+
+ /* Enable conversion of regular group. */
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ /* If software start has been selected, conversion starts immediately. */
+ /* If external trigger has been selected, conversion will start at next */
+ /* trigger event. */
+ SET_BIT(hadc->Instance->CR, ADC_CR_ADSTART);
+
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ }
+
+ /* Return function status */
+ return tmp_status;
+ }
+}
+
+/**
+ * @brief Stop multimode ADC conversion, disable ADC DMA transfer, disable ADC peripheral.
+ * @note Multimode is kept enabled after this function. MultiMode DMA bits
+ * (MDMA and DMACFG bits of common CCR register) are maintained. To disable
+ * Multimode (set with HAL_ADCEx_MultiModeConfigChannel()), ADC must be
+ * reinitialized using HAL_ADC_Init() or HAL_ADC_DeInit(), or the user can
+ * resort to HAL_ADCEx_DisableMultiMode() API.
+ * @note In case of DMA configured in circular mode, function
+ * HAL_ADC_Stop_DMA() must be called after this function with handle of
+ * ADC slave, to properly disable the DMA channel.
+ * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+ uint32_t tickstart;
+ ADC_HandleTypeDef tmphadcSlave;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+
+ /* 1. Stop potential multimode conversion on going, on regular and injected groups */
+ tmp_status = ADC_ConversionStop(hadc, ADC_REGULAR_INJECTED_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_status == HAL_OK)
+ {
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Procedure to disable the ADC peripheral: wait for conversions */
+ /* effectively stopped (ADC master and ADC slave), then disable ADC */
+
+ /* 1. Wait until ADSTP=0 for ADC master and ADC slave*/
+ tickstart = HAL_GetTick();
+
+ while(ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) ||
+ ADC_IS_CONVERSION_ONGOING_REGULAR(&tmphadcSlave) )
+ {
+ if((HAL_GetTick()-tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Disable the DMA channel (in case of DMA in circular mode or stop */
+ /* while DMA transfer is on going) */
+ /* Note: DMA channel of ADC slave should be stopped after this function */
+ /* with HAL_ADC_Stop_DMA() API. */
+ tmp_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_status == HAL_ERROR)
+ {
+ /* 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 peripherals: master and slave */
+ /* Update "tmp_status" only if DMA channel disabling passed, to keep in */
+ /* memory a potential failing status. */
+ if (tmp_status == HAL_OK)
+ {
+ /* Check if ADC are effectively disabled */
+ if ((ADC_Disable(hadc) == HAL_OK) &&
+ (ADC_Disable(&tmphadcSlave) == HAL_OK) )
+ {
+ tmp_status = HAL_OK;
+ }
+ }
+ else
+ {
+ ADC_Disable(hadc);
+ ADC_Disable(&tmphadcSlave);
+ }
+ /* Change ADC state (ADC master) */
+ /* Clear HAL_ADC_STATE_REG_BUSY and HAL_ADC_STATE_INJ_BUSY bits, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, (HAL_ADC_STATE_REG_BUSY|HAL_ADC_STATE_INJ_BUSY), HAL_ADC_STATE_READY);
+
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+/**
+ * @brief Return the last ADC Master and Slave regular conversions results when in multimode configuration.
+ * @param hadc: ADC handle of ADC Master (handle of ADC Slave must not be used)
+ * @retval The converted data values.
+ */
+uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef* hadc)
+{
+ ADC_Common_TypeDef *tmpADC_Common;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Pointer to the common control register */
+ tmpADC_Common = ADC_COMMON_REGISTER(hadc);
+
+ /* Return the multi mode conversion value */
+ return tmpADC_Common->CDR;
+}
+
+
+/**
+ * @brief Get ADC injected group conversion result.
+ * @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 Injected Channel1 selected
+ * @arg @ref ADC_INJECTED_RANK_2 Injected Channel2 selected
+ * @arg @ref ADC_INJECTED_RANK_3 Injected Channel3 selected
+ * @arg @ref ADC_INJECTED_RANK_4 Injected Channel4 selected
+ * @note Reading JDRy register automatically clears JEOC flag. To reset JEOS
+ * flag the user must resort to the macro
+ * __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOS).
+ * @retval None
+ */
+uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank)
+{
+ uint32_t tmp_jdr = 0;
+
+ /* 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.
+ */
+}
+
+/**
+ * @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.
+ */
+}
+
+
+
+/**
+ * @brief Stop ADC conversion of regular groups, disable ADC peripheral if no injected conversion is on-going.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_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_status == HAL_OK)
+ {
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc) == RESET)
+ {
+ /* 2. Disable the ADC peripheral */
+ tmp_status = ADC_Disable(hadc);
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit, set HAL_ADC_STATE_READY bit */
+ 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_status;
+}
+
+
+/**
+ * @brief Stop ADC conversion of regular groups when interruptions are enabled, disable ADC peripheral if no injected conversion is on-going.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop_IT(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_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_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 (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc) == RESET)
+ {
+ tmp_status = ADC_Disable(hadc);
+ /* if no issue reported */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit, set HAL_ADC_STATE_READY bit */
+ 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_status;
+}
+
+
+/**
+ * @brief Stop ADC conversion of regular groups and disable ADC DMA transfer, disable ADC peripheral if no injected conversion is on-going.
+ * @note HAL_ADCEx_RegularStop_DMA() function is dedicated to single-ADC mode only.
+ * For multimode (when multimode feature is available),
+ * HAL_ADCEx_RegularMultiModeStop_DMA() API must be used.
+ * @param hadc: ADC handle
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularStop_DMA(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* 1. Stop potential regular conversion on going */
+ tmp_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_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_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_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_status" only if DMA channel disabling passed, to keep in */
+ /* memory a potential failing status. */
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc) == RESET)
+ {
+ if (tmp_status == HAL_OK)
+ {
+ tmp_status = ADC_Disable(hadc);
+ }
+ else
+ {
+ ADC_Disable(hadc);
+ }
+
+ /* Check if ADC is effectively disabled */
+ if (tmp_status == HAL_OK)
+ {
+ /* Change ADC state */
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit, set HAL_ADC_STATE_READY bit */
+ 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_status;
+}
+
+
+/**
+ * @brief Stop DMA-based multimode ADC conversion, disable ADC DMA transfer, disable ADC peripheral if no injected conversion is on-going.
+ * @note Multimode is kept enabled after this function. Multimode DMA bits
+ * (MDMA and DMACFG bits of common CCR register) are maintained. To disable
+ * multimode (set with HAL_ADCEx_MultiModeConfigChannel()), ADC must be
+ * reinitialized using HAL_ADC_Init() or HAL_ADC_DeInit(), or the user can
+ * resort to HAL_ADCEx_DisableMultiMode() API.
+ * @note In case of DMA configured in circular mode, function
+ * HAL_ADCEx_RegularStop_DMA() must be called after this function with handle of
+ * ADC slave, to properly disable the DMA channel.
+ * @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_RegularMultiModeStop_DMA(ADC_HandleTypeDef* hadc)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+ uint32_t tickstart;
+ ADC_HandleTypeDef tmphadcSlave;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+
+ /* 1. Stop potential multimode conversion on going, on regular groups */
+ tmp_status = ADC_ConversionStop(hadc, ADC_REGULAR_GROUP);
+
+ /* Disable ADC peripheral if conversions are effectively stopped */
+ if (tmp_status == HAL_OK)
+ {
+ /* Clear HAL_ADC_STATE_REG_BUSY bit */
+ CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
+
+ /* Set a temporary handle of the ADC slave associated to the ADC master */
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ if (tmphadcSlave.Instance == NULL)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Procedure to disable the ADC peripheral: wait for conversions */
+ /* effectively stopped (ADC master and ADC slave), then disable ADC */
+
+ /* 1. Wait until ADSTP=0 for ADC master and ADC slave*/
+ tickstart = HAL_GetTick();
+
+ while(ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) ||
+ ADC_IS_CONVERSION_ONGOING_REGULAR(&tmphadcSlave) )
+ {
+ if((HAL_GetTick()-tickstart) > ADC_STOP_CONVERSION_TIMEOUT)
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Disable the DMA channel (in case of DMA in circular mode or stop */
+ /* while DMA transfer is on going) */
+ /* Note: DMA channel of ADC slave should be stopped after this function */
+ /* with HAL_ADCEx_RegularStop_DMA() API. */
+ tmp_status = HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Check if DMA channel effectively disabled */
+ if (tmp_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 peripherals: master and slave if no injected */
+ /* conversion is on-going. */
+ /* Update "tmp_status" only if DMA channel disabling passed, to keep in */
+ /* memory a potential failing status. */
+ if (tmp_status == HAL_OK)
+ {
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc) == RESET)
+ {
+ tmp_status = ADC_Disable(hadc);
+ if (tmp_status == HAL_OK)
+ {
+ if (ADC_IS_CONVERSION_ONGOING_INJECTED(&tmphadcSlave) == RESET)
+ {
+ tmp_status = ADC_Disable(&tmphadcSlave);
+ }
+ }
+ }
+
+ if (tmp_status == HAL_OK)
+ {
+ /* Both Master and Slave ADC's could be disabled. Update Master State */
+ /* Clear HAL_ADC_STATE_INJ_BUSY bit, set HAL_ADC_STATE_READY bit */
+ ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY, HAL_ADC_STATE_READY);
+ }
+ else
+ {
+ /* injected (Master or Slave) conversions are still on-going,
+ no Master State change */
+ }
+
+
+ }
+
+
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup ADCEx_Exported_Functions_Group2 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels on injected group
+ (+) Configure multimode when multimode feature is available
+ (+) Enable or Disable Injected Queue
+ (+) Disable ADC voltage regulator
+ (+) Enter ADC deep-power-down mode
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the ADC injected group and the selected channel to be linked to the injected group.
+ * @note Possibility to update parameters on the fly:
+ * This function initializes injected group, consecutive 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.
+ * For parameters constraints, see comments of structure
+ * "ADC_InjectionConfTypeDef".
+ * @note In case of usage of internal measurement channels (Vbat/VrefInt/TempSensor),
+ * The internal paths can be disabled using function HAL_ADC_DeInit().
+ * @note To reset injected sequencer, function HAL_ADCEx_InjectedStop() can
+ * be used.
+ * @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 None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_InjectionConfTypeDef* sConfigInjected)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+ ADC_Common_TypeDef *tmpADC_Common;
+ uint32_t tmpOffsetShifted;
+ uint32_t wait_loop_index = 0;
+
+
+ uint32_t tmp_JSQR_ContextQueueBeingBuilt = 0;
+
+ /* 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(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 == 1) )
+ {
+ /* 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)
+ && (sConfigInjected->ExternalTrigInjecConvEdge != ADC_EXTERNALTRIGINJECCONV_EDGE_NONE))
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = ( ADC_JSQR_RK(sConfigInjected->InjectedChannel, ADC_INJECTED_RANK_1) |
+ sConfigInjected->ExternalTrigInjecConv |
+ 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 == 0)
+ {
+ /* 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 = (uint32_t)0x00000000;
+
+ /* 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)
+ && (sConfigInjected->ExternalTrigInjecConvEdge != ADC_EXTERNALTRIGINJECCONV_EDGE_NONE))
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = ((sConfigInjected->InjectedNbrOfConversion - (uint32_t)1) |
+ sConfigInjected->ExternalTrigInjecConv |
+ sConfigInjected->ExternalTrigInjecConvEdge );
+ }
+ else
+ {
+ tmp_JSQR_ContextQueueBeingBuilt = ((sConfigInjected->InjectedNbrOfConversion - (uint32_t)1) );
+ }
+
+
+ } /* if (hadc->InjectionConfig.ChannelCount == 0) */
+
+
+ /* 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 == 0)
+ {
+ 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 (ADC_IS_CONVERSION_ONGOING_INJECTED(hadc) == RESET)
+ {
+
+ /* 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(sConfigInjected->QueueInjectedContext) |
+ ADC_CFGR_INJECT_DISCCONTINUOUS(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(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 */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET)
+ {
+ /* 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_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_INJ_FIELDS,
+ ADC_CFGR2_JOVSE |
+ sConfigInjected->InjecOversampling.Ratio |
+ sConfigInjected->InjecOversampling.RightBitShift );
+ }
+ else
+ {
+ /* Disable Regular OverSampling */
+ CLEAR_BIT( hadc->Instance->CFGR2, ADC_CFGR2_JOVSE);
+ }
+
+
+ /* Sampling time configuration of the selected channel */
+ /* if ADC_Channel_10 ... ADC_Channel_18 is selected */
+ if (sConfigInjected->InjectedChannel >= ADC_CHANNEL_10)
+ {
+ /* Clear the old sample time and set the new one */
+ ADC_SMPR2_SETTING(hadc, sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel);
+ }
+ else /* if ADC_Channel_0 ... ADC_Channel_9 is selected */
+ {
+ /* Clear the old sample time and set the new one */
+ ADC_SMPR1_SETTING(hadc, sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel);
+ }
+
+
+ /* 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);
+
+ switch (sConfigInjected->InjectedOffsetNumber)
+ {
+ case ADC_OFFSET_1:
+ /* Configure offset register 1: */
+ /* - Enable offset */
+ /* - Set channel number */
+ /* - Set offset value */
+ MODIFY_REG(hadc->Instance->OFR1,
+ ADC_OFR1_OFFSET1 | ADC_OFR1_OFFSET1_CH | ADC_OFR1_OFFSET1_EN,
+ ADC_OFR1_OFFSET1_EN | ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel) | tmpOffsetShifted);
+ break;
+
+ case ADC_OFFSET_2:
+ /* Configure offset register 2: */
+ /* - Enable offset */
+ /* - Set channel number */
+ /* - Set offset value */
+ MODIFY_REG(hadc->Instance->OFR2,
+ ADC_OFR2_OFFSET2 | ADC_OFR2_OFFSET2_CH | ADC_OFR2_OFFSET2_EN,
+ ADC_OFR2_OFFSET2_EN | ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel) | tmpOffsetShifted);
+ break;
+
+ case ADC_OFFSET_3:
+ /* Configure offset register 3: */
+ /* - Enable offset */
+ /* - Set channel number */
+ /* - Set offset value */
+ MODIFY_REG(hadc->Instance->OFR3,
+ ADC_OFR3_OFFSET3 | ADC_OFR3_OFFSET3_CH | ADC_OFR3_OFFSET3_EN,
+ ADC_OFR3_OFFSET3_EN | ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel) | tmpOffsetShifted);
+ break;
+
+ case ADC_OFFSET_4:
+ /* Configure offset register 1: */
+ /* - Enable offset */
+ /* - Set channel number */
+ /* - Set offset value */
+ MODIFY_REG(hadc->Instance->OFR4,
+ ADC_OFR4_OFFSET4 | ADC_OFR4_OFFSET4_CH | ADC_OFR4_OFFSET4_EN,
+ ADC_OFR4_OFFSET4_EN | ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel) | tmpOffsetShifted);
+ break;
+
+ /* Case ADC_OFFSET_NONE */
+ default :
+ /* Scan OFR1, OFR2, OFR3, OFR4 to check if the selected channel is enabled. If this is the case, offset OFRx is disabled. */
+ if (((hadc->Instance->OFR1) & ADC_OFR1_OFFSET1_CH) == ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel))
+ {
+ /* Disable offset OFR1*/
+ CLEAR_BIT(hadc->Instance->OFR1, ADC_OFR1_OFFSET1_EN);
+ }
+ if (((hadc->Instance->OFR2) & ADC_OFR2_OFFSET2_CH) == ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel))
+ {
+ /* Disable offset OFR2*/
+ CLEAR_BIT(hadc->Instance->OFR2, ADC_OFR2_OFFSET2_EN);
+ }
+ if (((hadc->Instance->OFR3) & ADC_OFR3_OFFSET3_CH) == ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel))
+ {
+ /* Disable offset OFR3*/
+ CLEAR_BIT(hadc->Instance->OFR3, ADC_OFR3_OFFSET3_EN);
+ }
+ if (((hadc->Instance->OFR4) & ADC_OFR4_OFFSET4_CH) == ADC_OFR_CHANNEL(sConfigInjected->InjectedChannel))
+ {
+ /* Disable offset OFR4*/
+ CLEAR_BIT(hadc->Instance->OFR4, ADC_OFR4_OFFSET4_EN);
+ }
+ break;
+ }
+
+ } /* if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET) */
+
+
+ /* 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 (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ /* Configuration of differential mode */
+ if (sConfigInjected->InjectedSingleDiff != ADC_DIFFERENTIAL_ENDED)
+ {
+ /* Disable differential mode (default mode: single-ended) */
+ CLEAR_BIT(hadc->Instance->DIFSEL, ADC_DIFSEL_CHANNEL(sConfigInjected->InjectedChannel));
+ }
+ else
+ {
+ /* Enable differential mode */
+ SET_BIT(hadc->Instance->DIFSEL, ADC_DIFSEL_CHANNEL(sConfigInjected->InjectedChannel));
+
+ /* Sampling time configuration of channel ADC_IN+1 (negative input).
+ Starting from channel 9, SMPR2 register must be configured. */
+ if (sConfigInjected->InjectedChannel >= ADC_CHANNEL_9)
+ {
+ /* Clear the old sample time and set the new one */
+ ADC_SMPR2_SETTING(hadc, sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel+1);
+ }
+ else /* For channels 0 to 8 */
+ {
+ /* Clear the old sample time and set the new one */
+ ADC_SMPR1_SETTING(hadc, sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel+1);
+ }
+ }
+
+
+ /* 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(). */
+
+ /* Configuration of common ADC parameters */
+
+ tmpADC_Common = ADC_COMMON_REGISTER(hadc);
+
+ /* If the requested internal measurement path has already been enabled, */
+ /* bypass the configuration processing. */
+ if (( (sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) &&
+ (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_TSEN)) ) ||
+ ( (sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT) &&
+ (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VBATEN)) ) ||
+ ( (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT) &&
+ (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_VREFEN)))
+ )
+ {
+ /* Configuration of common ADC parameters (continuation) */
+ /* Software is allowed to change common parameters only when all ADCs */
+ /* of the common group are disabled. */
+ if ((ADC_IS_ENABLE(hadc) == RESET) &&
+ (ADC_ANY_OTHER_ENABLED(hadc) == RESET) )
+ {
+ if (sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR)
+ {
+ if (ADC_TEMPERATURE_SENSOR_INSTANCE(hadc))
+ {
+ SET_BIT(tmpADC_Common->CCR, ADC_CCR_TSEN);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000));
+ while(wait_loop_index != 0)
+ {
+ wait_loop_index--;
+ }
+ }
+ }
+ else if (sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT)
+ {
+ if (ADC_BATTERY_VOLTAGE_INSTANCE(hadc))
+ {
+ SET_BIT(tmpADC_Common->CCR, ADC_CCR_VBATEN);
+ }
+ }
+ else if (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT)
+ {
+ if (ADC_VREFINT_INSTANCE(hadc))
+ {
+ SET_BIT(tmpADC_Common->CCR, ADC_CCR_VREFEN);
+ }
+ }
+ }
+ /* 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_status = HAL_ERROR;
+ }
+ }
+
+ } /* if (ADC_IS_ENABLE(hadc) == RESET) */
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+
+
+/**
+ * @brief Enable ADC multimode and configure multimode parameters
+ * @note Possibility to update parameters on the fly:
+ * This function initializes multimode parameters, following
+ * calls to this function can be used to reconfigure some parameters
+ * of structure "ADC_MultiModeTypeDef" on the fly, without resetting
+ * the ADCs.
+ * The setting of these parameters is conditioned to ADC state.
+ * For parameters constraints, see comments of structure
+ * "ADC_MultiModeTypeDef".
+ * @note To move back configuration from multimode to single mode, ADC must
+ * be reset (using function HAL_ADC_Init() ).
+ * @param hadc: Master ADC handle
+ * @param multimode : Structure of ADC multimode configuration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeConfigChannel(ADC_HandleTypeDef* hadc, ADC_MultiModeTypeDef* multimode)
+{
+ HAL_StatusTypeDef tmp_status = HAL_OK;
+ ADC_Common_TypeDef *tmpADC_Common;
+ ADC_HandleTypeDef tmphadcSlave;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
+ assert_param(IS_ADC_MULTIMODE(multimode->Mode));
+ assert_param(IS_ADC_DMA_ACCESS_MULTIMODE(multimode->DMAAccessMode));
+ assert_param(IS_ADC_SAMPLING_DELAY(multimode->TwoSamplingDelay));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
+
+ /* Parameters update conditioned to ADC state: */
+ /* Parameters that can be updated when ADC is disabled or enabled without */
+ /* conversion on going on regular group: */
+ /* - Multimode DMA configuration */
+ /* - Multimode DMA mode */
+ if ( (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)
+ && (ADC_IS_CONVERSION_ONGOING_REGULAR(&tmphadcSlave) == RESET) )
+ {
+
+ /* Pointer to the common control register */
+ tmpADC_Common = ADC_COMMON_REGISTER(hadc);
+
+ MODIFY_REG(tmpADC_Common->CCR, ADC_CCR_MDMA | ADC_CCR_DMACFG,
+ multimode->DMAAccessMode |
+ ADC_CCR_MULTI_DMACONTREQ(hadc->Init.DMAContinuousRequests));
+
+ /* Parameters that can be updated only when ADC is disabled: */
+ /* - Multimode mode selection */
+ /* - Multimode delay */
+ if ((ADC_IS_ENABLE(hadc) == RESET) &&
+ (ADC_IS_ENABLE(&tmphadcSlave) == RESET) )
+ {
+ /* Configuration of ADC common group ADC1&ADC2 */
+ /* - set the selected multimode */
+ /* - Set delay between two sampling phases */
+ /* Note: Delay range depends on selected resolution: */
+ /* from 1 to 12 clock cycles for 12 bits */
+ /* from 1 to 10 clock cycles for 10 bits, */
+ /* from 1 to 8 clock cycles for 8 bits */
+ /* from 1 to 6 clock cycles for 6 bits */
+ /* If a higher delay is selected, it will be clipped to maximum delay */
+ /* range */
+
+ MODIFY_REG(tmpADC_Common->CCR, ADC_CCR_DUAL | ADC_CCR_DELAY,
+ multimode->Mode | multimode->TwoSamplingDelay );
+ }
+
+
+ }
+ /* If one of the ADC sharing the same common group is enabled, no update */
+ /* could be done on neither of the multimode structure parameters. */
+ else
+ {
+ /* Update ADC state machine to error */
+ SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
+
+ tmp_status = HAL_ERROR;
+ }
+
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return tmp_status;
+}
+
+
+/**
+ * @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)
+{
+
+ /* Parameter can be set only if no conversion is on-going */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET)
+ {
+ 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);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+}
+
+/**
+ * @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)
+{
+
+ /* Parameter can be set only if no conversion is on-going */
+ if (ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED(hadc) == RESET)
+ {
+ SET_BIT(hadc->Instance->CFGR, ADC_CFGR_JQDIS);
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+}
+
+
+/**
+ * @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)
+{
+
+ /* ADVREGEN can be written only when the ADC is disabled */
+ if (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ CLEAR_BIT(hadc->Instance->CR, ADC_CR_ADVREGEN);
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @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)
+{
+
+ /* DEEPPWD can be written only when the ADC is disabled */
+ if (ADC_IS_ENABLE(hadc) == RESET)
+ {
+ SET_BIT(hadc->Instance->CR, ADC_CR_DEEPPWD);
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_can.c b/stmhal/hal/l4/src/stm32l4xx_hal_can.c
new file mode 100644
index 000000000..455664ba3
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_can.c
@@ -0,0 +1,1404 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_can.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief CAN HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Controller Area Network (CAN) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Error functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Enable the CAN controller interface clock using
+ __HAL_RCC_CAN1_CLK_ENABLE() for CAN1.
+
+ (#) CAN pins configuration
+ (++) Enable the clock for the CAN GPIOs using the following function:
+ __HAL_RCC_GPIOx_CLK_ENABLE();
+ (++) Connect and configure the involved CAN pins using the
+ following function HAL_GPIO_Init();
+
+ (#) Initialize and configure the CAN using HAL_CAN_Init() function.
+
+ (#) Transmit the desired CAN frame using HAL_CAN_Transmit() or
+ HAL_CAN_Transmit_IT() function.
+
+ (#) Receive a CAN frame using HAL_CAN_Receive() or HAL_CAN_Receive_IT() function.
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Start the CAN peripheral transmission and wait the end of this operation
+ using HAL_CAN_Transmit(), at this stage user can specify the value of timeout
+ according to his end application
+ (+) Start the CAN peripheral reception and wait the end of this operation
+ using HAL_CAN_Receive(), at this stage user can specify the value of timeout
+ according to his end application
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Start the CAN peripheral transmission using HAL_CAN_Transmit_IT()
+ (+) Start the CAN peripheral reception using HAL_CAN_Receive_IT()
+ (+) Use HAL_CAN_IRQHandler() called under the used CAN Interrupt subroutine
+ (+) At CAN end of transmission HAL_CAN_TxCpltCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_CAN_TxCpltCallback
+ (+) In case of CAN Error, HAL_CAN_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_CAN_ErrorCallback
+
+ *** CAN HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in CAN HAL driver.
+
+ (+) __HAL_CAN_ENABLE_IT: Enable the specified CAN interrupts
+ (+) __HAL_CAN_DISABLE_IT: Disable the specified CAN interrupts
+ (+) __HAL_CAN_GET_IT_SOURCE: Check if the specified CAN interrupt source is enabled or disabled
+ (+) __HAL_CAN_CLEAR_FLAG: Clear the CAN's pending flags
+ (+) __HAL_CAN_GET_FLAG: Get the selected CAN's flag status
+
+ [..]
+ (@) You can refer to the CAN HAL driver header file for more useful macros
+
+ @endverbatim
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup CAN CAN
+ * @brief CAN driver modules
+ * @{
+ */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup CAN_Private_Constants CAN Private Constants
+ * @{
+ */
+#define CAN_TIMEOUT_VALUE 10
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup CAN_Private_Functions CAN Private Functions
+ * @{
+ */
+static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber);
+static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup CAN_Exported_Functions CAN Exported Functions
+ * @{
+ */
+
+/** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the CAN.
+ (+) De-initialize the CAN.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the CAN peripheral according to the specified parameters
+ * in the CAN_InitStruct structure and initialize the associated handle.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan)
+{
+ uint32_t status = CAN_INITSTATUS_FAILED; /* Default init status */
+ uint32_t tickstart = 0;
+
+ /* Check CAN handle */
+ if(hcan == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
+ assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TTCM));
+ assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ABOM));
+ assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AWUM));
+ assert_param(IS_FUNCTIONAL_STATE(hcan->Init.NART));
+ assert_param(IS_FUNCTIONAL_STATE(hcan->Init.RFLM));
+ assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TXFP));
+ assert_param(IS_CAN_MODE(hcan->Init.Mode));
+ assert_param(IS_CAN_SJW(hcan->Init.SJW));
+ assert_param(IS_CAN_BS1(hcan->Init.BS1));
+ assert_param(IS_CAN_BS2(hcan->Init.BS2));
+ assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler));
+
+ if(hcan->State == HAL_CAN_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hcan->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware */
+ HAL_CAN_MspInit(hcan);
+ }
+
+ /* Initialize the CAN state*/
+ hcan->State = HAL_CAN_STATE_BUSY;
+
+ /* Exit from sleep mode */
+ hcan->Instance->MCR &= (~(uint32_t)CAN_MCR_SLEEP);
+
+ /* Request initialisation */
+ hcan->Instance->MCR |= CAN_MCR_INRQ ;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait the acknowledge */
+ while((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
+ {
+ if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
+ {
+ hcan->State= HAL_CAN_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check acknowledge */
+ if ((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
+ {
+ /* Set the time triggered communication mode */
+ if (hcan->Init.TTCM == ENABLE)
+ {
+ hcan->Instance->MCR |= CAN_MCR_TTCM;
+ }
+ else
+ {
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TTCM;
+ }
+
+ /* Set the automatic bus-off management */
+ if (hcan->Init.ABOM == ENABLE)
+ {
+ hcan->Instance->MCR |= CAN_MCR_ABOM;
+ }
+ else
+ {
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_ABOM;
+ }
+
+ /* Set the automatic wake-up mode */
+ if (hcan->Init.AWUM == ENABLE)
+ {
+ hcan->Instance->MCR |= CAN_MCR_AWUM;
+ }
+ else
+ {
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_AWUM;
+ }
+
+ /* Set the no automatic retransmission */
+ if (hcan->Init.NART == ENABLE)
+ {
+ hcan->Instance->MCR |= CAN_MCR_NART;
+ }
+ else
+ {
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_NART;
+ }
+
+ /* Set the receive FIFO locked mode */
+ if (hcan->Init.RFLM == ENABLE)
+ {
+ hcan->Instance->MCR |= CAN_MCR_RFLM;
+ }
+ else
+ {
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_RFLM;
+ }
+
+ /* Set the transmit FIFO priority */
+ if (hcan->Init.TXFP == ENABLE)
+ {
+ hcan->Instance->MCR |= CAN_MCR_TXFP;
+ }
+ else
+ {
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TXFP;
+ }
+
+ /* Set the bit timing register */
+ hcan->Instance->BTR = (uint32_t)((uint32_t)hcan->Init.Mode) | \
+ ((uint32_t)hcan->Init.SJW) | \
+ ((uint32_t)hcan->Init.BS1) | \
+ ((uint32_t)hcan->Init.BS2) | \
+ ((uint32_t)hcan->Init.Prescaler - 1);
+
+ /* Request leave initialisation */
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_INRQ;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait the acknowledge */
+ while((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
+ {
+ if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
+ {
+ hcan->State= HAL_CAN_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check acknowledged */
+ if ((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
+ {
+ status = CAN_INITSTATUS_SUCCESS;
+ }
+ }
+
+ if(status == CAN_INITSTATUS_SUCCESS)
+ {
+ /* Set CAN error code to none */
+ hcan->ErrorCode = HAL_CAN_ERROR_NONE;
+
+ /* Initialize the CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Initialize the CAN state */
+ hcan->State = HAL_CAN_STATE_ERROR;
+
+ /* Return function status */
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the CAN reception filter according to the specified
+ * parameters in the CAN_FilterInitStruct.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @param sFilterConfig: pointer to a CAN_FilterConfTypeDef structure that
+ * contains the filter configuration information.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig)
+{
+ uint32_t filternbrbitpos = 0;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcan);
+
+ /* Check the parameters */
+ assert_param(IS_CAN_FILTER_NUMBER(sFilterConfig->FilterNumber));
+ assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode));
+ assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale));
+ assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment));
+ assert_param(IS_FUNCTIONAL_STATE(sFilterConfig->FilterActivation));
+ assert_param(IS_CAN_BANKNUMBER(sFilterConfig->BankNumber));
+
+ filternbrbitpos = ((uint32_t)1) << sFilterConfig->FilterNumber;
+
+ /* Initialisation mode for the filter */
+ CAN1->FMR |= (uint32_t)CAN_FMR_FINIT;
+
+ /* Filter Deactivation */
+ CAN1->FA1R &= ~(uint32_t)filternbrbitpos;
+
+ /* Filter Scale */
+ if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)
+ {
+ /* 16-bit scale for the filter */
+ CAN1->FS1R &= ~(uint32_t)filternbrbitpos;
+
+ /* First 16-bit identifier and First 16-bit mask */
+ /* Or First 16-bit identifier and Second 16-bit identifier */
+ CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
+ ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16) |
+ (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdLow);
+
+ /* Second 16-bit identifier and Second 16-bit mask */
+ /* Or Third 16-bit identifier and Fourth 16-bit identifier */
+ CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR2 =
+ ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16) |
+ (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh);
+ }
+
+ if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)
+ {
+ /* 32-bit scale for the filter */
+ CAN1->FS1R |= filternbrbitpos;
+ /* 32-bit identifier or First 32-bit identifier */
+ CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
+ ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) << 16) |
+ (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdLow);
+ /* 32-bit mask or Second 32-bit identifier */
+ CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR2 =
+ ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16) |
+ (0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdLow);
+ }
+
+ /* Filter Mode */
+ if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK)
+ {
+ /*Id/Mask mode for the filter*/
+ CAN1->FM1R &= ~(uint32_t)filternbrbitpos;
+ }
+ else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
+ {
+ /*Identifier list mode for the filter*/
+ CAN1->FM1R |= (uint32_t)filternbrbitpos;
+ }
+
+ /* Filter FIFO assignment */
+ if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0)
+ {
+ /* FIFO 0 assignation for the filter */
+ CAN1->FFA1R &= ~(uint32_t)filternbrbitpos;
+ }
+
+ if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO1)
+ {
+ /* FIFO 1 assignation for the filter */
+ CAN1->FFA1R |= (uint32_t)filternbrbitpos;
+ }
+
+ /* Filter activation */
+ if (sFilterConfig->FilterActivation == ENABLE)
+ {
+ CAN1->FA1R |= filternbrbitpos;
+ }
+
+ /* Leave the initialisation mode for the filter */
+ CAN1->FMR &= ~((uint32_t)CAN_FMR_FINIT);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the CAN peripheral registers to their default reset values.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan)
+{
+ /* Check CAN handle */
+ if(hcan == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
+
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY;
+
+ /* DeInit the low level hardware */
+ HAL_CAN_MspDeInit(hcan);
+
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the CAN MSP.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval None
+ */
+__weak void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcan);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CAN_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the CAN MSP.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval None
+ */
+__weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcan);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CAN_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CAN_Exported_Functions_Group2 Input and Output operation functions
+ * @brief I/O operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Transmit a CAN frame message.
+ (+) Receive a CAN frame message.
+ (+) Enter CAN peripheral in sleep mode.
+ (+) Wake up the CAN peripheral from sleep mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initiate and transmit a CAN frame message.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
+{
+ uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
+ assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
+ assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
+
+ /* Process locked */
+ __HAL_LOCK(hcan);
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_RX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX;
+ }
+
+ /* Select one empty transmit mailbox */
+ if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
+ {
+ transmitmailbox = 0;
+ }
+ else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
+ {
+ transmitmailbox = 1;
+ }
+ else if ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
+ {
+ transmitmailbox = 2;
+ }
+
+ if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX)
+ {
+ /* Set up the Id */
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
+ if (hcan->pTxMsg->IDE == CAN_ID_STD)
+ {
+ assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21) | \
+ hcan->pTxMsg->RTR);
+ }
+ else
+ {
+ assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3) | \
+ hcan->pTxMsg->IDE | \
+ hcan->pTxMsg->RTR);
+ }
+
+ /* Set up the DLC */
+ hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
+ hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;
+ hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
+
+ /* Set up the data field */
+ hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3] << 24) |
+ ((uint32_t)hcan->pTxMsg->Data[2] << 16) |
+ ((uint32_t)hcan->pTxMsg->Data[1] << 8) |
+ ((uint32_t)hcan->pTxMsg->Data[0]));
+ hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7] << 24) |
+ ((uint32_t)hcan->pTxMsg->Data[6] << 16) |
+ ((uint32_t)hcan->pTxMsg->Data[5] << 8) |
+ ((uint32_t)hcan->pTxMsg->Data[4]));
+ /* Request transmission */
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check End of transmission flag */
+ while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ hcan->State = HAL_CAN_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_RX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Initiate and transmit a CAN frame message in Interrupt mode.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
+{
+ uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
+
+ /* Check the parameters */
+ assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
+ assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
+ assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
+
+ if((hcan->State == HAL_CAN_STATE_READY) || (hcan->State == HAL_CAN_STATE_BUSY_RX))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hcan);
+
+ /* Select one empty transmit mailbox */
+ if((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
+ {
+ transmitmailbox = 0;
+ }
+ else if((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
+ {
+ transmitmailbox = 1;
+ }
+ else if((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
+ {
+ transmitmailbox = 2;
+ }
+
+ if(transmitmailbox != CAN_TXSTATUS_NOMAILBOX)
+ {
+ /* Set up the Id */
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
+ if(hcan->pTxMsg->IDE == CAN_ID_STD)
+ {
+ assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21) | \
+ hcan->pTxMsg->RTR);
+ }
+ else
+ {
+ assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3) | \
+ hcan->pTxMsg->IDE | \
+ hcan->pTxMsg->RTR);
+ }
+
+ /* Set up the DLC */
+ hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
+ hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;
+ hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
+
+ /* Set up the data field */
+ hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3] << 24) |
+ ((uint32_t)hcan->pTxMsg->Data[2] << 16) |
+ ((uint32_t)hcan->pTxMsg->Data[1] << 8) |
+ ((uint32_t)hcan->pTxMsg->Data[0]));
+ hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7] << 24) |
+ ((uint32_t)hcan->pTxMsg->Data[6] << 16) |
+ ((uint32_t)hcan->pTxMsg->Data[5] << 8) |
+ ((uint32_t)hcan->pTxMsg->Data[4]));
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_RX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX;
+ }
+
+ /* Set CAN error code to none */
+ hcan->ErrorCode = HAL_CAN_ERROR_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Enable interrupts: */
+ /* - Enable Error warning Interrupt */
+ /* - Enable Error passive Interrupt */
+ /* - Enable Bus-off Interrupt */
+ /* - Enable Last error code Interrupt */
+ /* - Enable Error Interrupt */
+ /* - Enable Transmit mailbox empty Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
+ CAN_IT_EPV |
+ CAN_IT_BOF |
+ CAN_IT_LEC |
+ CAN_IT_ERR |
+ CAN_IT_TME );
+
+ /* Request transmission */
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive a correct CAN frame.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @param FIFONumber: FIFO number.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef* hcan, uint8_t FIFONumber, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_CAN_FIFO(FIFONumber));
+
+ /* Process locked */
+ __HAL_LOCK(hcan);
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_RX;
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check pending message */
+ while(__HAL_CAN_MSG_PENDING(hcan, FIFONumber) == 0)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ hcan->State = HAL_CAN_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Get the Id */
+ hcan->pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
+ if (hcan->pRxMsg->IDE == CAN_ID_STD)
+ {
+ hcan->pRxMsg->StdId = (uint32_t)0x000007FF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21);
+ }
+ else
+ {
+ hcan->pRxMsg->ExtId = (uint32_t)0x1FFFFFFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3);
+ }
+
+ hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
+ /* Get the DLC */
+ hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
+ /* Get the FMI */
+ hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8);
+ /* Get the data field */
+ hcan->pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
+ hcan->pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8);
+ hcan->pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16);
+ hcan->pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24);
+ hcan->pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
+ hcan->pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8);
+ hcan->pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16);
+ hcan->pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24);
+
+ /* Release the FIFO */
+ if(FIFONumber == CAN_FIFO0)
+ {
+ /* Release FIFO0 */
+ __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
+ }
+ else /* FIFONumber == CAN_FIFO1 */
+ {
+ /* Release FIFO1 */
+ __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
+ }
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive a correct CAN frame in Interrupt mode.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @param FIFONumber: FIFO number.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
+{
+ /* Check the parameters */
+ assert_param(IS_CAN_FIFO(FIFONumber));
+
+ if((hcan->State == HAL_CAN_STATE_READY) || (hcan->State == HAL_CAN_STATE_BUSY_TX))
+ {
+ /* Process locked */
+ __HAL_LOCK(hcan);
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_RX;
+ }
+
+ /* Set CAN error code to none */
+ hcan->ErrorCode = HAL_CAN_ERROR_NONE;
+
+ /* Enable interrupts: */
+ /* - Enable Error warning Interrupt */
+ /* - Enable Error passive Interrupt */
+ /* - Enable Bus-off Interrupt */
+ /* - Enable Last error code Interrupt */
+ /* - Enable Error Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
+ CAN_IT_EPV |
+ CAN_IT_BOF |
+ CAN_IT_LEC |
+ CAN_IT_ERR );
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ if(FIFONumber == CAN_FIFO0)
+ {
+ /* Enable FIFO 0 message pending Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0);
+ }
+ else
+ {
+ /* Enable FIFO 1 message pending Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP1);
+ }
+
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enter the Sleep (low power) mode.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef* hcan)
+{
+ uint32_t tickstart = 0;
+
+ /* Process locked */
+ __HAL_LOCK(hcan);
+
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY;
+
+ /* Request Sleep mode */
+ hcan->Instance->MCR = (((hcan->Instance->MCR) & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
+
+ /* Sleep mode status */
+ if ((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK)
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_ERROR;
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait the acknowledge */
+ while((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK)
+ {
+ if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
+ {
+ hcan->State = HAL_CAN_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Wake up the CAN peripheral from sleep mode (after that the CAN peripheral
+ * is in the normal mode).
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef* hcan)
+{
+ uint32_t tickstart = 0;
+
+ /* Process locked */
+ __HAL_LOCK(hcan);
+
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY;
+
+ /* Wake up request */
+ hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_SLEEP;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Sleep mode status */
+ while((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)
+ {
+ if((HAL_GetTick()-tickstart) > CAN_TIMEOUT_VALUE)
+ {
+ hcan->State= HAL_CAN_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ return HAL_TIMEOUT;
+ }
+ }
+ if((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_ERROR;
+ }
+
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle CAN interrupt request.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval None
+ */
+void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
+{
+ /* Check End of transmission flag */
+ if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
+ {
+ if((__HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0)) ||
+ (__HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1)) ||
+ (__HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2)))
+ {
+ /* Call transmit function */
+ CAN_Transmit_IT(hcan);
+ }
+ }
+
+ /* Check End of reception flag for FIFO0 */
+ if((__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0)) &&
+ (__HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0) != 0))
+ {
+ /* Call receive function */
+ CAN_Receive_IT(hcan, CAN_FIFO0);
+ }
+
+ /* Check End of reception flag for FIFO1 */
+ if((__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1)) &&
+ (__HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1) != 0))
+ {
+ /* Call receive function */
+ CAN_Receive_IT(hcan, CAN_FIFO1);
+ }
+
+ /* Check Error Warning Flag */
+ if((__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)))
+ {
+ /* Set CAN error code to EWG error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
+ /* No need for clear of Error Warning Flag as read-only */
+ }
+
+ /* Check Error Passive Flag */
+ if((__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)))
+ {
+ /* Set CAN error code to EPV error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
+ /* No need for clear of Error Passive Flag as read-only */
+ }
+
+ /* Check Bus-Off Flag */
+ if((__HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)))
+ {
+ /* Set CAN error code to BOF error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
+ /* No need for clear of Bus-Off Flag as read-only */
+ }
+
+ /* Check Last error code Flag */
+ if((!HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC)) &&
+ (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR)))
+ {
+ switch(hcan->Instance->ESR & CAN_ESR_LEC)
+ {
+ case(CAN_ESR_LEC_0):
+ /* Set CAN error code to STF error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_STF;
+ break;
+ case(CAN_ESR_LEC_1):
+ /* Set CAN error code to FOR error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_FOR;
+ break;
+ case(CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
+ /* Set CAN error code to ACK error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_ACK;
+ break;
+ case(CAN_ESR_LEC_2):
+ /* Set CAN error code to BR error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_BR;
+ break;
+ case(CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
+ /* Set CAN error code to BD error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_BD;
+ break;
+ case(CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
+ /* Set CAN error code to CRC error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_CRC;
+ break;
+ default:
+ break;
+ }
+
+ /* Clear Last error code Flag */
+ hcan->Instance->ESR &= ~(CAN_ESR_LEC);
+ }
+
+ /* Call the Error call Back in case of Errors */
+ if(hcan->ErrorCode != HAL_CAN_ERROR_NONE)
+ {
+ /* Clear ERRI bit */
+ SET_BIT(hcan->Instance->MSR, CAN_MSR_ERRI);
+ /* Set the CAN state ready to be able to start again the process */
+ hcan->State = HAL_CAN_STATE_READY;
+ /* Call Error callback function */
+ HAL_CAN_ErrorCallback(hcan);
+ }
+}
+
+/**
+ * @brief Transmission complete callback in non-blocking mode.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval None
+ */
+__weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcan);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CAN_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Reception complete callback in non-blocking mode.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval None
+ */
+__weak void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcan);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CAN_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error CAN callback.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval None
+ */
+__weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hcan);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_CAN_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CAN_Exported_Functions_Group3 Peripheral State and Error functions
+ * @brief CAN Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to :
+ (+) Check the CAN state.
+ (+) Check CAN Errors detected during interrupt process.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the CAN handle state.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL state
+ */
+HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan)
+{
+ /* Return CAN handle state */
+ return hcan->State;
+}
+
+/**
+ * @brief Return the CAN error code.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval CAN Error Code
+ */
+uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan)
+{
+ return hcan->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup CAN_Private_Functions CAN Private Functions
+ * @{
+ */
+/**
+ * @brief Initiate and transmit a CAN frame message.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
+{
+ /* Disable Transmit mailbox empty Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_TME);
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX)
+ {
+ /* Disable interrupts: */
+ /* - Disable Error warning Interrupt */
+ /* - Disable Error passive Interrupt */
+ /* - Disable Bus-off Interrupt */
+ /* - Disable Last error code Interrupt */
+ /* - Disable Error Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
+ CAN_IT_EPV |
+ CAN_IT_BOF |
+ CAN_IT_LEC |
+ CAN_IT_ERR );
+ }
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_RX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+ }
+
+ /* Transmission complete callback */
+ HAL_CAN_TxCpltCallback(hcan);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Receive a correct CAN frame.
+ * @param hcan: Pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @param FIFONumber: Specify the FIFO number
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
+{
+ /* Get the Id */
+ hcan->pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
+ if (hcan->pRxMsg->IDE == CAN_ID_STD)
+ {
+ hcan->pRxMsg->StdId = (uint32_t)0x000007FF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21);
+ }
+ else
+ {
+ hcan->pRxMsg->ExtId = (uint32_t)0x1FFFFFFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3);
+ }
+
+ hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
+ /* Get the DLC */
+ hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
+ /* Get the FMI */
+ hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8);
+ /* Get the data field */
+ hcan->pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
+ hcan->pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8);
+ hcan->pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16);
+ hcan->pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24);
+ hcan->pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
+ hcan->pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8);
+ hcan->pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16);
+ hcan->pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24);
+ /* Release the FIFO */
+ /* Release FIFO0 */
+ if (FIFONumber == CAN_FIFO0)
+ {
+ __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
+
+ /* Disable FIFO 0 message pending Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP0);
+ }
+ /* Release FIFO1 */
+ else /* FIFONumber == CAN_FIFO1 */
+ {
+ __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
+
+ /* Disable FIFO 1 message pending Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP1);
+ }
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_RX)
+ {
+ /* Disable interrupts: */
+ /* - Disable Error warning Interrupt */
+ /* - Disable Error passive Interrupt */
+ /* - Disable Bus-off Interrupt */
+ /* - Disable Last error code Interrupt */
+ /* - Disable Error Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
+ CAN_IT_EPV |
+ CAN_IT_BOF |
+ CAN_IT_LEC |
+ CAN_IT_ERR );
+ }
+
+ if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)
+ {
+ /* Disable CAN state */
+ hcan->State = HAL_CAN_STATE_BUSY_TX;
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+ }
+
+ /* Receive complete callback */
+ HAL_CAN_RxCpltCallback(hcan);
+
+ /* Return function status */
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_CAN_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_cortex.c b/stmhal/hal/l4/src/stm32l4xx_hal_cortex.c
new file mode 100644
index 000000000..7ff673dc5
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_cortex.c
@@ -0,0 +1,492 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_cortex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @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
+ *
+ @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-M4 exceptions are managed by CMSIS functions.
+
+ (#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping() function.
+ (#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority().
+ (#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ().
+
+ -@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ pre-emption is no more possible.
+ The pending IRQ priority will be managed only by the sub priority.
+
+ -@- IRQ priority order (sorted by highest to lowest priority):
+ (+@) Lowest pre-emption priority
+ (+@) Lowest sub priority
+ (+@) Lowest hardware priority (IRQ number)
+
+ [..]
+ *** 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 (0x0F).
+ (++) 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 stm32l4xx_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
+ ******************************************************************************
+
+ The table below gives the allowed values of the pre-emption priority and subpriority according
+ to the Priority Grouping configuration performed by HAL_NVIC_SetPriorityGrouping() function.
+
+ ==========================================================================================================================
+ NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description
+ ==========================================================================================================================
+ NVIC_PRIORITYGROUP_0 | 0 | 0-15 | 0 bit for pre-emption priority
+ | | | 4 bits for subpriority
+ --------------------------------------------------------------------------------------------------------------------------
+ NVIC_PRIORITYGROUP_1 | 0-1 | 0-7 | 1 bit for pre-emption priority
+ | | | 3 bits for subpriority
+ --------------------------------------------------------------------------------------------------------------------------
+ NVIC_PRIORITYGROUP_2 | 0-3 | 0-3 | 2 bits for pre-emption priority
+ | | | 2 bits for subpriority
+ --------------------------------------------------------------------------------------------------------------------------
+ NVIC_PRIORITYGROUP_3 | 0-7 | 0-1 | 3 bits for pre-emption priority
+ | | | 1 bit for subpriority
+ --------------------------------------------------------------------------------------------------------------------------
+ NVIC_PRIORITYGROUP_4 | 0-15 | 0 | 4 bits for pre-emption priority
+ | | | 0 bit for subpriority
+ ==========================================================================================================================
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_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 (stm32l4xxxx.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 = 0x00;
+
+ /* 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.
+ * @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
+ * function should be called before.
+ * @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 (stm32l4xxxx.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 (stm32l4xxxx.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 (stm32l4xxxx.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 (stm32l4xxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_SetPendingIRQ(IRQn_Type 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 (stm32l4xxxx.h))
+ * @retval status: - 0 Interrupt status is not pending.
+ * - 1 Interrupt status is pending.
+ */
+uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type 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 (stm32l4xxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ /* Clear pending interrupt */
+ NVIC_ClearPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Get active interrupt (read the active register in NVIC and return the active bit).
+ * @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 (stm32l4xxxx.h))
+ * @retval status: - 0 Interrupt status is not pending.
+ * - 1 Interrupt status is pending.
+ */
+uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
+{
+ /* Return 1 if active else 0 */
+ return NVIC_GetActive(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 == 1)
+/**
+ * @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) != RESET)
+ {
+ /* 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 = 0x00;
+ MPU->RASR = 0x00;
+ }
+}
+#endif /* __MPU_PRESENT */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_dac.c b/stmhal/hal/l4/src/stm32l4xx_hal_dac.c
new file mode 100644
index 000000000..d797a232c
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_dac.c
@@ -0,0 +1,1183 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_dac.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief DAC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Digital to Analog Converter (DAC) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### DAC Peripheral features #####
+ ==============================================================================
+ [..]
+ *** DAC Channels ***
+ ====================
+ [..]
+ STM32L4 devices integrate two 12-bit Digital Analog Converters
+
+ The 2 converters (i.e. channel1 & channel2)
+ can be used independently or simultaneously (dual mode):
+ (#) DAC channel1 with DAC_OUT1 (PA4) as output or connected to on-chip
+ peripherals (ex. OPAMPs, comparators).
+ (#) DAC channel2 with DAC_OUT2 (PA5) as output or connected to on-chip
+ peripherals (ex. OPAMPs, comparators).
+
+ *** DAC Triggers ***
+ ====================
+ [..]
+ Digital to Analog conversion can be non-triggered using DAC_TRIGGER_NONE
+ and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register.
+ [..]
+ Digital to Analog conversion can be triggered by:
+ (#) External event: EXTI Line 9 (any GPIOx_PIN_9) using DAC_TRIGGER_EXT_IT9.
+ The used pin (GPIOx_PIN_9) must be configured in input mode.
+
+ (#) Timers TRGO: TIM2, TIM3, TIM4, TIM5, TIM6 and TIM7
+ (DAC_TRIGGER_T2_TRGO, DAC_TRIGGER_T3_TRGO...)
+
+ (#) Software using DAC_TRIGGER_SOFTWARE
+
+ *** DAC Buffer mode feature ***
+ ===============================
+ [..]
+ Each DAC channel integrates an output buffer that can be used to
+ reduce the output impedance, and to drive external loads directly
+ without having to add an external operational amplifier.
+ To enable, the output buffer use
+ sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
+ [..]
+ (@) Refer to the device datasheet for more details about output
+ impedance value with and without output buffer.
+
+ *** DAC connect feature ***
+ ===============================
+ [..]
+ Each DAC channel can be connected internally.
+ To connect, use
+ sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
+
+ *** GPIO configurations guidelines ***
+ =====================
+ [..]
+ When a DAC channel is used (ex channel1 on PA4) and the other is not
+ (ex channel2 on PA5 is configured in Analog and disabled).
+ Channel1 may disturb channel2 as coupling effect.
+ Note that there is no coupling on channel2 as soon as channel2 is turned on.
+ Coupling on adjacent channel could be avoided as follows:
+ when unused PA5 is configured as INPUT PULL-UP or DOWN.
+ PA5 is configured in ANALOG just before it is turned on.
+
+ *** DAC Sample and Hold feature ***
+ ========================
+ [..]
+ For each converter, 2 modes are supported: normal mode and
+ "sample and hold" mode (i.e. low power mode).
+ In the sample and hold mode, the DAC core converts data, then holds the
+ converted voltage on a capacitor. When not converting, the DAC cores and
+ buffer are completely turned off between samples and the DAC output is
+ tri-stated, therefore reducing the overall power consumption. A new
+ stabilization period is needed before each new conversion.
+
+ The sample and hold allow setting internal or external voltage @
+ low power consumption cost (output value can be at any given rate either
+ by CPU or DMA).
+
+ The Sample and hold block and registers uses either LSI & run in
+ several power modes: run mode, sleep mode, low power run, low power sleep
+ mode & stop1 mode.
+
+ Low power stop1 mode allows only static conversion.
+
+ To enable Sample and Hold mode
+ Enable LSI using HAL_RCC_OscConfig with RCC_OSCILLATORTYPE_LSI &
+ RCC_LSI_ON parameters.
+
+ Use DAC_InitStructure.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_ENABLE;
+ & DAC_ChannelConfTypeDef.DAC_SampleAndHoldConfig.DAC_SampleTime,
+ DAC_HoldTime & DAC_RefreshTime;
+
+
+
+ *** DAC calibration feature ***
+ ===================================
+ [..]
+ (#) The 2 converters (channel1 & channel2) provide calibration capabilities.
+ (++) Calibration aims at correcting some offset of output buffer.
+ (++) The DAC uses either factory calibration settings OR user defined
+ calibration (trimming) settings (i.e. trimming mode).
+ (++) The user defined settings can be figured out using self calibration
+ handled by HAL_DACEx_SelfCalibrate.
+ (++) HAL_DACEx_SelfCalibrate:
+ (+++) Runs automatically the calibration.
+ (+++) Enables the user trimming mode
+ (+++) Updates a structure with trimming values with fresh calibration
+ results.
+ The user may store the calibration results for larger
+ (ex monitoring the trimming as a function of temperature
+ for instance)
+
+ *** DAC wave generation feature ***
+ ===================================
+ [..]
+ Both DAC channels can be used to generate
+ (#) Noise wave
+ (#) Triangle wave
+
+ *** DAC data format ***
+ =======================
+ [..]
+ The DAC data format can be:
+ (#) 8-bit right alignment using DAC_ALIGN_8B_R
+ (#) 12-bit left alignment using DAC_ALIGN_12B_L
+ (#) 12-bit right alignment using DAC_ALIGN_12B_R
+
+ *** DAC data value to voltage correspondence ***
+ ================================================
+ [..]
+ The analog output voltage on each DAC channel pin is determined
+ by the following equation:
+ [..]
+ DAC_OUTx = VREF+ * DOR / 4095
+ (+) with DOR is the Data Output Register
+ [..]
+ VEF+ is the input voltage reference (refer to the device datasheet)
+ [..]
+ e.g. To set DAC_OUT1 to 0.7V, use
+ (+) Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
+
+ *** DMA requests ***
+ =====================
+ [..]
+ A DMA1 request can be generated when an external trigger (but not a software trigger)
+ occurs if DMA1 requests are enabled using HAL_DAC_Start_DMA().
+ DMA requests are mapped as following:
+ (#) DAC channel1: mapped either on
+ (++) DMA1 request 6 channel3
+ (++) or DMA2 request channel4 which must be already configured
+ (#) DAC channel2: mapped either on
+ (++) DMA1 request 5 channel4
+ (++) or DMA2 request 3 channel5 which must be already configured
+ [..]
+ (@) For Dual mode and specific signal (Triangle and noise) generation please
+ refer to Extended Features Driver description
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) DAC APB clock must be enabled to get write access to DAC
+ registers using HAL_DAC_Init()
+ (+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode.
+ (+) Configure the DAC channel using HAL_DAC_ConfigChannel() function.
+ (+) Enable the DAC channel using HAL_DAC_Start() or HAL_DAC_Start_DMA() functions.
+
+ *** Calibration mode IO operation ***
+ ======================================
+ [..]
+ (+) Retrieve the factory trimming (calibration settings) using HAL_DACEx_GetTrimOffset()
+ (+) Run the calibration using HAL_DACEx_SelfCalibrate()
+ (+) Update the trimming while DAC running using HAL_DACEx_SetUserTrimming()
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Start the DAC peripheral using HAL_DAC_Start()
+ (+) To read the DAC last data output value, use the HAL_DAC_GetValue() function.
+ (+) Stop the DAC peripheral using HAL_DAC_Stop()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Start the DAC peripheral using HAL_DAC_Start_DMA(), at this stage the user specify the length
+ of data to be transferred at each end of conversion
+ (+) At the middle of data transfer HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ (+) At The end of data transfer HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
+ (+) In case of transfer Error, HAL_DAC_ErrorCallbackCh1() function is executed and user can
+ add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1
+ (+) In case of DMA underrun, DAC interruption triggers and execute internal function HAL_DAC_IRQHandler.
+ HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2() and
+ add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1()
+ (+) Stop the DAC peripheral using HAL_DAC_Stop_DMA()
+
+ *** DAC HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in DAC HAL driver.
+
+ (+) __HAL_DAC_ENABLE : Enable the DAC peripheral
+ (+) __HAL_DAC_DISABLE : Disable the DAC peripheral
+ (+) __HAL_DAC_CLEAR_FLAG: Clear the DAC's pending flags
+ (+) __HAL_DAC_GET_FLAG: Get the selected DAC's flag status
+
+ [..]
+ (@) You can refer to the DAC HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+ /** @defgroup DAC DAC
+ * @brief DAC driver modules
+ * @{
+ */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup DAC_Private_Constants DAC Private Constants
+ * @{
+ */
+#define TIMEOUT_DAC_CALIBCONFIG ((uint32_t)1) /* 1ms */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup DAC_Private_Functions DAC Private Functions
+ * @{
+ */
+static void DAC_DMAConvCpltCh1(DMA_HandleTypeDef *hdma);
+static void DAC_DMAErrorCh1(DMA_HandleTypeDef *hdma);
+static void DAC_DMAHalfConvCpltCh1(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+/* Exported functions -------------------------------------------------------*/
+
+/** @defgroup DAC_Exported_Functions DAC Exported Functions
+ * @{
+ */
+
+/** @defgroup DAC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the DAC.
+ (+) De-initialize the DAC.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the DAC peripheral according to the specified parameters
+ * in the DAC_InitStruct and initialize the associated handle.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef* hdac)
+{
+ /* Check DAC handle */
+ if(hdac == NULL)
+ {
+ return HAL_ERROR;
+ }
+ /* Check the parameters */
+ assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
+
+ if(hdac->State == HAL_DAC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hdac->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware */
+ HAL_DAC_MspInit(hdac);
+ }
+
+ /* Initialize the DAC state*/
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Set DAC error code to none */
+ hdac->ErrorCode = HAL_DAC_ERROR_NONE;
+
+ /* Initialize the DAC state*/
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Deinitialize the DAC peripheral registers to their default reset values.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_DeInit(DAC_HandleTypeDef* hdac)
+{
+ /* Check DAC handle */
+ if(hdac == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* DeInit the low level hardware */
+ HAL_DAC_MspDeInit(hdac);
+
+ /* Set DAC error code to none */
+ hdac->ErrorCode = HAL_DAC_ERROR_NONE;
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the DAC MSP.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the DAC MSP.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_MspDeInit(DAC_HandleTypeDef* hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion.
+ (+) Stop conversion.
+ (+) Start conversion and enable DMA transfer.
+ (+) Stop conversion and disable DMA transfer.
+ (+) Get result of conversion.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables DAC and starts conversion of channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, Channel);
+
+ if(Channel == DAC_CHANNEL_1)
+ {
+ /* Check if software trigger enabled */
+ if((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == (DAC_CR_TEN1 | DAC_CR_TSEL1))
+ {
+ /* Enable the selected DAC software conversion */
+ SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG1);
+ }
+ }
+ else
+ {
+ /* Check if software trigger enabled */
+ if((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_CR_TEN2 | DAC_CR_TSEL2))
+ {
+ /* Enable the selected DAC software conversion*/
+ SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG2);
+ }
+ }
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables DAC and stop conversion of channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Disable the Peripheral */
+ __HAL_DAC_DISABLE(hdac, Channel);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables DAC and starts conversion of channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param pData: The destination peripheral Buffer address.
+ * @param Length: The length of data to be transferred from memory to DAC peripheral
+ * @param Alignment: Specifies the data alignment for DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_ALIGN(Alignment));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ if(Channel == DAC_CHANNEL_1)
+ {
+ /* Set the DMA transfer complete callback for channel1 */
+ hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
+
+ /* Set the DMA half transfer complete callback for channel1 */
+ hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
+
+ /* Set the DMA error callback for channel1 */
+ hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
+
+ /* Enable the selected DAC channel1 DMA request */
+ SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
+
+ /* Case of use of channel 1 */
+ switch(Alignment)
+ {
+ case DAC_ALIGN_12B_R:
+ /* Get DHR12R1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12R1;
+ break;
+ case DAC_ALIGN_12B_L:
+ /* Get DHR12L1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12L1;
+ break;
+ case DAC_ALIGN_8B_R:
+ /* Get DHR8R1 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR8R1;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* Set the DMA transfer complete callback for channel2 */
+ hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
+
+ /* Set the DMA half transfer complete callback for channel2 */
+ hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
+
+ /* Set the DMA error callback for channel2 */
+ hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
+
+ /* Enable the selected DAC channel2 DMA request */
+ SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
+
+ /* Case of use of channel 2 */
+ switch(Alignment)
+ {
+ case DAC_ALIGN_12B_R:
+ /* Get DHR12R2 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12R2;
+ break;
+ case DAC_ALIGN_12B_L:
+ /* Get DHR12L2 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR12L2;
+ break;
+ case DAC_ALIGN_8B_R:
+ /* Get DHR8R2 address */
+ tmpreg = (uint32_t)&hdac->Instance->DHR8R2;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Enable the DMA channel */
+ if(Channel == DAC_CHANNEL_1)
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
+ }
+ else
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, Channel);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables DAC and stop conversion of channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Disable the selected DAC channel DMA request */
+ hdac->Instance->CR &= ~(DAC_CR_DMAEN1 << Channel);
+
+ /* Disable the Peripheral */
+ __HAL_DAC_DISABLE(hdac, Channel);
+
+ /* Disable the DMA channel */
+ /* Channel1 is used */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Disable the DMA channel */
+ status = HAL_DMA_Abort(hdac->DMA_Handle1);
+
+ /* Disable the DAC DMA underrun interrupt */
+ __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
+ }
+ else /* Channel2 is used for */
+ {
+ /* Disable the DMA channel */
+ status = HAL_DMA_Abort(hdac->DMA_Handle2);
+
+ /* Disable the DAC DMA underrun interrupt */
+ __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
+ }
+
+ /* Check if DMA Channel effectively disabled */
+ if (status != HAL_OK)
+ {
+ /* Update DAC state machine to error */
+ hdac->State = HAL_DAC_STATE_ERROR;
+ }
+ else
+ {
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/* DAC channel 2 is available on top of DAC channel 1 */
+
+/**
+ * @brief Handles DAC interrupt request
+ * This function uses the interruption of DMA
+ * underrun.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+void HAL_DAC_IRQHandler(DAC_HandleTypeDef* hdac)
+{
+ if(__HAL_DAC_GET_IT_SOURCE(hdac, DAC_IT_DMAUDR1))
+ {
+ /* Check underrun flag of DAC channel 1 */
+ if(__HAL_DAC_GET_FLAG(hdac, DAC_FLAG_DMAUDR1))
+ {
+ /* Change DAC state to error state */
+ hdac->State = HAL_DAC_STATE_ERROR;
+
+ /* Set DAC error code to chanel1 DMA underrun error */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH1);
+
+ /* Clear the underrun flag */
+ __HAL_DAC_CLEAR_FLAG(hdac,DAC_FLAG_DMAUDR1);
+
+ /* Disable the selected DAC channel1 DMA request */
+ CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
+
+ /* Error callback */
+ HAL_DAC_DMAUnderrunCallbackCh1(hdac);
+ }
+ }
+ if(__HAL_DAC_GET_IT_SOURCE(hdac, DAC_IT_DMAUDR2))
+ {
+ /* Check underrun flag of DAC channel 1 */
+ if(__HAL_DAC_GET_FLAG(hdac, DAC_FLAG_DMAUDR2))
+ {
+ /* Change DAC state to error state */
+ hdac->State = HAL_DAC_STATE_ERROR;
+
+ /* Set DAC error code to channel2 DMA underrun error */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH2);
+
+ /* Clear the underrun flag */
+ __HAL_DAC_CLEAR_FLAG(hdac,DAC_FLAG_DMAUDR2);
+
+ /* Disable the selected DAC channel1 DMA request */
+ CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
+
+ /* Error callback */
+ HAL_DACEx_DMAUnderrunCallbackCh2(hdac);
+ }
+ }
+}
+
+/**
+ * @brief Set the specified data holding register value for DAC channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param Alignment: Specifies the data alignment.
+ * This parameter can be one of the following values:
+ * @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @param Data: Data to be loaded in the selected data holding register.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
+{
+ __IO uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_ALIGN(Alignment));
+ assert_param(IS_DAC_DATA(Data));
+
+ tmp = (uint32_t)hdac->Instance;
+ if(Channel == DAC_CHANNEL_1)
+ {
+ tmp += DAC_DHR12R1_ALIGNMENT(Alignment);
+ }
+ else
+ {
+ tmp += DAC_DHR12R2_ALIGNMENT(Alignment);
+ }
+
+ /* Set the DAC channel selected data holding register */
+ *(__IO uint32_t *) tmp = Data;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Conversion complete callback in non-blocking mode for Channel1
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef* hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_ConvCpltCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Conversion half DMA transfer callback in non-blocking mode for Channel1
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef* hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_ConvHalfCpltCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error DAC callback for Channel1.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_ErrorCallbackCh1(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_ErrorCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA underrun DAC callback for channel1.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DAC_DMAUnderrunCallbackCh1(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DAC_DMAUnderrunCallbackCh1 could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels.
+ (+) Set the specified data holding register value for DAC channel.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the last data output value of the selected DAC channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval The selected DAC channel data output value.
+ */
+uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Returns the DAC channel data output register value */
+ if(Channel == DAC_CHANNEL_1)
+ {
+ return hdac->Instance->DOR1;
+ }
+ else
+ {
+ return hdac->Instance->DOR2;
+ }
+}
+
+/**
+ * @brief Configures the selected DAC channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param sConfig: DAC configuration structure.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef* hdac, DAC_ChannelConfTypeDef* sConfig, uint32_t Channel)
+{
+ uint32_t tmpreg1 = 0, tmpreg2 = 0;
+ uint32_t tickstart = 0;
+
+ /* Check the DAC parameters */
+ assert_param(IS_DAC_TRIGGER(sConfig->DAC_Trigger));
+ assert_param(IS_DAC_OUTPUT_BUFFER_STATE(sConfig->DAC_OutputBuffer));
+ assert_param(IS_DAC_CHIP_CONNECTION(sConfig->DAC_ConnectOnChipPeripheral));
+ assert_param(IS_DAC_TRIMMING(sConfig->DAC_UserTrimming));
+ if ((sConfig->DAC_UserTrimming) == DAC_TRIMMING_USER)
+ {
+ assert_param(IS_DAC_TRIMMINGVALUE(sConfig->DAC_TrimmingValue));
+ }
+ assert_param(IS_DAC_SAMPLEANDHOLD(sConfig->DAC_SampleAndHold));
+ if ((sConfig->DAC_SampleAndHold) == DAC_SAMPLEANDHOLD_ENABLE)
+ {
+ assert_param(IS_DAC_SAMPLETIME(sConfig->DAC_SampleAndHoldConfig.DAC_SampleTime));
+ assert_param(IS_DAC_HOLDTIME(sConfig->DAC_SampleAndHoldConfig.DAC_HoldTime));
+ assert_param(IS_DAC_REFRESHTIME(sConfig->DAC_SampleAndHoldConfig.DAC_RefreshTime));
+ }
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ if(sConfig->DAC_SampleAndHold == DAC_SAMPLEANDHOLD_ENABLE)
+ /* Sample on old configuration */
+ {
+ /* SampleTime */
+ if (Channel == DAC_CHANNEL_1)
+ {
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ /* SHSR1 can be written when BWST1 equals RESET */
+ while (((hdac->Instance->SR) & DAC_SR_BWST1)!= RESET)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart) > TIMEOUT_DAC_CALIBCONFIG)
+ {
+ /* Update error code */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_TIMEOUT);
+
+ /* Change the DMA state */
+ hdac->State = HAL_DAC_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ HAL_Delay(1);
+ hdac->Instance->SHSR1 = sConfig->DAC_SampleAndHoldConfig.DAC_SampleTime;
+ }
+ else /* Channel 2 */
+ {
+ /* SHSR2 can be written when BWST2 equals RESET */
+
+ while (((hdac->Instance->SR) & DAC_SR_BWST2)!= RESET)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart) > TIMEOUT_DAC_CALIBCONFIG)
+ {
+ /* Update error code */
+ SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_TIMEOUT);
+
+ /* Change the DMA state */
+ hdac->State = HAL_DAC_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ HAL_Delay(1);
+ hdac->Instance->SHSR2 = sConfig->DAC_SampleAndHoldConfig.DAC_SampleTime;
+ }
+ /* HoldTime */
+ hdac->Instance->SHHR = (sConfig->DAC_SampleAndHoldConfig.DAC_HoldTime)<<Channel;
+ /* RefreshTime */
+ hdac->Instance->SHRR = (sConfig->DAC_SampleAndHoldConfig.DAC_RefreshTime)<<Channel;
+ }
+
+ if(sConfig->DAC_UserTrimming == DAC_TRIMMING_USER)
+ /* USER TRIMMING */
+ {
+ /* Get the DAC CCR value */
+ tmpreg1 = hdac->Instance->CCR;
+ /* Clear trimming value */
+ tmpreg1 &= ~(((uint32_t)(DAC_CCR_OTRIM1)) << Channel);
+ /* Configure for the selected trimming offset */
+ tmpreg2 = sConfig->DAC_TrimmingValue;
+ /* Calculate CCR register value depending on DAC_Channel */
+ tmpreg1 |= tmpreg2 << Channel;
+ /* Write to DAC CCR */
+ hdac->Instance->CCR = tmpreg1;
+ }
+ /* else factory trimming is used (factory setting are available at reset)*/
+ /* SW Nothing has nothing to do */
+
+ /* Get the DAC MCR value */
+ tmpreg1 = hdac->Instance->MCR;
+ /* Clear DAC_MCR_MODE2_0, DAC_MCR_MODE2_1 and DAC_MCR_MODE2_2 bits */
+ tmpreg1 &= ~(((uint32_t)(DAC_MCR_MODE1)) << Channel);
+ /* Configure for the selected DAC channel: mode, buffer output & on chip peripheral connect */
+ tmpreg2 = (sConfig->DAC_SampleAndHold | sConfig->DAC_OutputBuffer | sConfig->DAC_ConnectOnChipPeripheral);
+ /* Calculate MCR register value depending on DAC_Channel */
+ tmpreg1 |= tmpreg2 << Channel;
+ /* Write to DAC MCR */
+ hdac->Instance->MCR = tmpreg1;
+
+ /* DAC in normal operating mode hence clear DAC_CR_CENx bit */
+ CLEAR_BIT (hdac->Instance->CR, DAC_CR_CEN1 << Channel);
+
+ /* Get the DAC CR value */
+ tmpreg1 = hdac->Instance->CR;
+ /* Clear TENx, TSELx, WAVEx and MAMPx bits */
+ tmpreg1 &= ~(((uint32_t)(DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1)) << Channel);
+ /* Configure for the selected DAC channel: trigger */
+ /* Set TSELx and TENx bits according to DAC_Trigger value */
+ tmpreg2 = (sConfig->DAC_Trigger);
+ /* Calculate CR register value depending on DAC_Channel */
+ tmpreg1 |= tmpreg2 << Channel;
+ /* Write to DAC CR */
+ hdac->Instance->CR = tmpreg1;
+
+ /* Disable wave generation */
+ hdac->Instance->CR &= ~(DAC_CR_WAVE1 << Channel);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Exported_Functions_Group4 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 DAC state.
+ (+) Check the DAC Errors.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief return the DAC handle state
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval HAL state
+ */
+HAL_DAC_StateTypeDef HAL_DAC_GetState(DAC_HandleTypeDef* hdac)
+{
+ /* Return DAC handle state */
+ return hdac->State;
+}
+
+
+/**
+ * @brief Return the DAC error code
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval DAC Error Code
+ */
+uint32_t HAL_DAC_GetError(DAC_HandleTypeDef *hdac)
+{
+ return hdac->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup DAC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief DMA conversion complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void DAC_DMAConvCpltCh1(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef* hdac = ( DAC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ HAL_DAC_ConvCpltCallbackCh1(hdac);
+
+ hdac->State= HAL_DAC_STATE_READY;
+}
+
+/**
+ * @brief DMA half transfer complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void DAC_DMAHalfConvCpltCh1(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef* hdac = ( DAC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ /* Conversion complete callback */
+ HAL_DAC_ConvHalfCpltCallbackCh1(hdac);
+}
+
+/**
+ * @brief DMA error callback
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void DAC_DMAErrorCh1(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef* hdac = ( DAC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Set DAC error code to DMA error */
+ hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
+
+ HAL_DAC_ErrorCallbackCh1(hdac);
+
+ hdac->State= HAL_DAC_STATE_READY;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_dac_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_dac_ex.c
new file mode 100644
index 000000000..c3446257b
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_dac_ex.c
@@ -0,0 +1,620 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_dac_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief DAC HAL module driver.
+ * This file provides firmware functions to manage the extended
+ * functionalities of the DAC peripheral.
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) When Dual mode is enabled (i.e. DAC Channel1 and Channel2 are used simultaneously) :
+ Use HAL_DACEx_DualGetValue() to get digital data to be converted and use
+ HAL_DACEx_DualSetValue() to set digital value to converted simultaneously in Channel 1 and Channel 2.
+ (+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
+ (+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
+
+ (+) HAL_DACEx_SelfCalibrate to calibrate one DAC channel.
+ (+) HAL_DACEx_SetUserTrimming to set user trimming value.
+ (+) HAL_DACEx_GetTrimOffset to retrieve trimming value (factory setting
+ after reset, user setting if HAL_DACEx_SetUserTrimming have been used
+ at least one time after reset).
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DACEx DACEx
+ * @brief DAC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup DACEx_Exported_Functions DACEx Exported Functions
+ * @{
+ */
+
+/** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
+ * @brief Extended IO operation functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended features functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion.
+ (+) Stop conversion.
+ (+) Start conversion and enable DMA transfer.
+ (+) Stop conversion and disable DMA transfer.
+ (+) Get result of conversion.
+ (+) Get result of dual mode conversion.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable or disable the selected DAC channel wave generation.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * DAC_CHANNEL_1 / DAC_CHANNEL_2
+ * @param Amplitude: Select max triangle amplitude.
+ * This parameter can be one of the following values:
+ * @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
+ * @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
+ * @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
+ * @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
+ * @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
+ * @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
+ * @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
+ * @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
+ * @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
+ * @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
+ * @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
+ * @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Amplitude)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the triangle wave generation for the selected DAC channel */
+ MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1)|(DAC_CR_MAMP1))<<Channel, (DAC_CR_WAVE1_1 | Amplitude) << Channel);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable or disable the selected DAC channel wave generation.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * DAC_CHANNEL_1 / DAC_CHANNEL_2
+ * @param Amplitude: Unmask DAC channel LFSR for noise wave generation.
+ * This parameter can be one of the following values:
+ * @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
+ * @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Amplitude)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Enable the noise wave generation for the selected DAC channel */
+ MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1)|(DAC_CR_MAMP1))<<Channel, (DAC_CR_WAVE1_0 | Amplitude) << Channel);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+
+
+/**
+ * @brief Set the specified data holding register value for dual DAC channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param Alignment: Specifies the data alignment for dual channel DAC.
+ * This parameter can be one of the following values:
+ * DAC_ALIGN_8B_R: 8bit right data alignment selected
+ * DAC_ALIGN_12B_L: 12bit left data alignment selected
+ * DAC_ALIGN_12B_R: 12bit right data alignment selected
+ * @param Data1: Data for DAC Channel2 to be loaded in the selected data holding register.
+ * @param Data2: Data for DAC Channel1 to be loaded in the selected data holding register.
+ * @note In dual mode, a unique register access is required to write in both
+ * DAC channels at the same time.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef* hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
+{
+ uint32_t data = 0, tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_ALIGN(Alignment));
+ assert_param(IS_DAC_DATA(Data1));
+ assert_param(IS_DAC_DATA(Data2));
+
+ /* Calculate and set dual DAC data holding register value */
+ if (Alignment == DAC_ALIGN_8B_R)
+ {
+ data = ((uint32_t)Data2 << 8) | Data1;
+ }
+ else
+ {
+ data = ((uint32_t)Data2 << 16) | Data1;
+ }
+
+ tmp = (uint32_t)hdac->Instance;
+ tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
+
+ /* Set the dual DAC selected data holding register */
+ *(__IO uint32_t *)tmp = data;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Conversion complete callback in non-blocking mode for Channel2.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef* hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Conversion half DMA transfer callback in non-blocking mode for Channel2.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef* hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error DAC callback for Channel2.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA underrun DAC callback for Channel2.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval None
+ */
+__weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdac);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Run the self calibration of one DAC channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param sConfig: DAC channel configuration structure.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval Updates DAC_TrimmingValue. , DAC_UserTrimming set to DAC_UserTrimming
+ * @retval HAL status
+ * @note Calibration runs about 7 ms.
+ */
+
+HAL_StatusTypeDef HAL_DACEx_SelfCalibrate (DAC_HandleTypeDef* hdac, DAC_ChannelConfTypeDef* sConfig, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ __IO uint32_t tmp = 0;
+ uint32_t trimmingvalue = 0;
+ uint32_t delta;
+
+ /* store/restore channel configuration structure purpose */
+ uint32_t oldmodeconfiguration = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Check the DAC handle allocation */
+ /* Check if DAC running */
+ if((hdac == NULL) || (hdac->State == HAL_DAC_STATE_BUSY))
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Store configuration */
+ oldmodeconfiguration = (hdac->Instance->MCR & (DAC_MCR_MODE1 << Channel));
+
+ /* Disable the selected DAC channel */
+ CLEAR_BIT ((hdac->Instance->CR), (DAC_CR_EN1 << Channel));
+
+ /* Set mode in MCR for calibration */
+ MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << Channel), 0);
+
+ /* Set DAC Channel1 DHR register to the middle value */
+ /* HAL_DAC_SetValue(hdac, Channel, DAC_ALIGN_12B_R, 0x0800); */
+ tmp = (uint32_t)hdac->Instance;
+ if(Channel == DAC_CHANNEL_1)
+ {
+ tmp += DAC_DHR12R1_ALIGNMENT(DAC_ALIGN_12B_R);
+ }
+ else
+ {
+ tmp += DAC_DHR12R2_ALIGNMENT(DAC_ALIGN_12B_R);
+ }
+ *(__IO uint32_t *) tmp = 0x0800;
+
+ /* Enable the selected DAC channel calibration */
+ /* i.e. set DAC_CR_CENx bit */
+ SET_BIT ((hdac->Instance->CR), (DAC_CR_CEN1 << Channel));
+
+ /* Init trimming counter */
+ /* Medium value */
+ trimmingvalue = 16;
+ delta = 8;
+ while (delta != 0)
+ {
+ /* Set candidate trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1<<Channel), (trimmingvalue<<Channel));
+
+ /* tOFFTRIMmax delay x ms as per datasheet (electrical characteristics */
+ /* i.e. minimum time needed between two calibration steps */
+ HAL_Delay(1);
+
+ if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1<<Channel)) == RESET)
+ {
+ /* DAC_SR_CAL_FLAGx is HIGH try higher trimming */
+ trimmingvalue += delta;
+ }
+ else
+ {
+ /* DAC_SR_CAL_FLAGx is LOW try lower trimming */
+ trimmingvalue -= delta;
+ }
+ delta >>= 1;
+ }
+
+ /* Still need to check if right calibration is current value or one step below */
+ /* Indeed the first value that causes the DAC_SR_CAL_FLAGx bit to change from 0 to 1 */
+ /* Set candidate trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1<<Channel), (trimmingvalue<<Channel));
+
+ /* tOFFTRIMmax delay x ms as per datasheet (electrical characteristics */
+ /* i.e. minimum time needed between two calibration steps */
+ HAL_Delay(1);
+
+ if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1<<Channel)) == RESET)
+ {
+ /* OPAMP_CSR_OUTCAL is actually one value more */
+ trimmingvalue++;
+ /* Set right trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1<<Channel), (trimmingvalue<<Channel));
+ }
+
+ /* Disable the selected DAC channel calibration */
+ /* i.e. clear DAC_CR_CENx bit */
+ CLEAR_BIT ((hdac->Instance->CR), (DAC_CR_CEN1 << Channel));
+
+ sConfig->DAC_TrimmingValue = trimmingvalue;
+ sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
+
+ /* Restore configuration */
+ MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << Channel), oldmodeconfiguration);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ return status;
+}
+
+/**
+ * @brief Set the trimming mode and trimming value (user trimming mode applied).
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @param sConfig: DAC configuration structure updated with new DAC trimming value.
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @param NewTrimmingValue: DAC new trimming value
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_DACEx_SetUserTrimming (DAC_HandleTypeDef* hdac, DAC_ChannelConfTypeDef* sConfig, uint32_t Channel, uint32_t NewTrimmingValue)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(Channel));
+ assert_param(IS_DAC_NEWTRIMMINGVALUE(NewTrimmingValue));
+
+ /* Check the DAC handle allocation */
+ if(hdac == NULL)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Set new trimming */
+ MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1<<Channel), (NewTrimmingValue<<Channel));
+
+ /* Update trimming mode */
+ sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
+ sConfig->DAC_TrimmingValue = NewTrimmingValue;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdac);
+
+ return status;
+}
+
+/**
+ * @brief Return the DAC trimming value.
+ * @param hdac : DAC handle
+ * @param Channel: The selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @retval Trimming value : range: 0->31
+ *
+ */
+
+uint32_t HAL_DACEx_GetTrimOffset (DAC_HandleTypeDef *hdac, uint32_t Channel)
+{
+ uint32_t trimmingvalue = 0;
+
+ /* Check the DAC handle allocation */
+ /* And not in Reset state */
+ if((hdac == NULL) || (hdac->State == HAL_DAC_STATE_RESET))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_DAC_CHANNEL(Channel));
+
+ /* Retrieve trimming */
+ trimmingvalue = ((hdac->Instance->CCR & (DAC_CCR_OTRIM1 << Channel)) >> Channel);
+ }
+ return trimmingvalue;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure channels.
+ (+) Set the specified data holding register value for DAC channel.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the last data output value of the selected DAC channel.
+ * @param hdac: pointer to a DAC_HandleTypeDef structure that contains
+ * the configuration information for the specified DAC.
+ * @retval The selected DAC channel data output value.
+ */
+uint32_t HAL_DACEx_DualGetValue(DAC_HandleTypeDef* hdac)
+{
+ uint32_t tmp = 0;
+
+ tmp |= hdac->Instance->DOR1;
+
+ tmp |= hdac->Instance->DOR2 << 16;
+
+ /* Returns the DAC channel data output register value */
+ return tmp;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup DACEx_Private_Functions DACEx private functions
+ * @brief Extended private functions
+ * @{
+ */
+
+/**
+ * @brief DMA conversion complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef* hdac = ( DAC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ HAL_DACEx_ConvCpltCallbackCh2(hdac);
+
+ hdac->State= HAL_DAC_STATE_READY;
+}
+
+/**
+ * @brief DMA half transfer complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef* hdac = ( DAC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ /* Conversion complete callback */
+ HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
+}
+
+/**
+ * @brief DMA error callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
+{
+ DAC_HandleTypeDef* hdac = ( DAC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Set DAC error code to DMA error */
+ hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
+
+ HAL_DACEx_ErrorCallbackCh2(hdac);
+
+ hdac->State= HAL_DAC_STATE_READY;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_dma.c b/stmhal/hal/l4/src/stm32l4xx_hal_dma.c
new file mode 100644
index 000000000..81ed8eabc
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_dma.c
@@ -0,0 +1,899 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_dma.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @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
+ @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.
+
+ (#) 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 by customization of function pointer XferCpltCallback and
+ XferErrorCallback (i.e. a member of DMA handle structure).
+
+ *** DMA HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used 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 has occurred or not.
+
+ [..]
+ (@) You can refer to the DMA HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMA DMA
+ * @brief DMA HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup DMA_Private_Constants DMA Private Constants
+ * @{
+ */
+#define HAL_TIMEOUT_DMA_ABORT ((uint32_t)1000) /* 1s */
+/**
+ * @}
+ */
+
+/* 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);
+/**
+ * @}
+ */
+
+/* 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 = 0;
+
+ /* 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));
+ if(hdma->Init.Direction != DMA_MEMORY_TO_MEMORY)
+ {
+ assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));
+ }
+
+ if(hdma->State == HAL_DMA_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hdma->Lock = HAL_UNLOCKED;
+ }
+
+ /* 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 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));
+
+ /* 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;
+
+ /* Set request selection */
+ if(hdma->Init.Direction != DMA_MEMORY_TO_MEMORY)
+ {
+ /* Write to DMA channel selection register */
+ if (hdma->Instance == DMA1_Channel1)
+ {
+ /*Reset request selection for DMA1 Channel1*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C1S;
+
+ /* Configure request selection for DMA1 Channel1 */
+ DMA1_CSELR->CSELR |= hdma->Init.Request;
+ }
+ else if (hdma->Instance == DMA1_Channel2)
+ {
+ /*Reset request selection for DMA1 Channel2*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C2S;
+
+ /* Configure request selection for DMA1 Channel2 */
+ DMA1_CSELR->CSELR |= (uint32_t)(hdma->Init.Request << 4);
+ }
+ else if (hdma->Instance == DMA1_Channel3)
+ {
+ /*Reset request selection for DMA1 Channel3*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C3S;
+
+ /* Configure request selection for DMA1 Channel3 */
+ DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 8);
+ }
+ else if (hdma->Instance == DMA1_Channel4)
+ {
+ /*Reset request selection for DMA1 Channel4*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C4S;
+
+ /* Configure request selection for DMA1 Channel4 */
+ DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 12);
+ }
+ else if (hdma->Instance == DMA1_Channel5)
+ {
+ /*Reset request selection for DMA1 Channel5*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C5S;
+
+ /* Configure request selection for DMA1 Channel5 */
+ DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 16);
+ }
+ else if (hdma->Instance == DMA1_Channel6)
+ {
+ /*Reset request selection for DMA1 Channel6*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C6S;
+
+ /* Configure request selection for DMA1 Channel6 */
+ DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 20);
+ }
+ else if (hdma->Instance == DMA1_Channel7)
+ {
+ /*Reset request selection for DMA1 Channel7*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C7S;
+
+ /* Configure request selection for DMA1 Channel7 */
+ DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 24);
+ }
+ else if (hdma->Instance == DMA2_Channel1)
+ {
+ /*Reset request selection for DMA2 Channel1*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C1S;
+
+ /* Configure request selection for DMA2 Channel1 */
+ DMA2_CSELR->CSELR |= hdma->Init.Request;
+ }
+ else if (hdma->Instance == DMA2_Channel2)
+ {
+ /*Reset request selection for DMA2 Channel2*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C2S;
+
+ /* Configure request selection for DMA2 Channel2 */
+ DMA2_CSELR->CSELR |= (uint32_t)(hdma->Init.Request << 4);
+ }
+ else if (hdma->Instance == DMA2_Channel3)
+ {
+ /*Reset request selection for DMA2 Channel3*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C3S;
+
+ /* Configure request selection for DMA2 Channel3 */
+ DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 8);
+ }
+ else if (hdma->Instance == DMA2_Channel4)
+ {
+ /*Reset request selection for DMA2 Channel4*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C4S;
+
+ /* Configure request selection for DMA2 Channel4 */
+ DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 12);
+ }
+ else if (hdma->Instance == DMA2_Channel5)
+ {
+ /*Reset request selection for DMA2 Channel5*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C5S;
+
+ /* Configure request selection for DMA2 Channel5 */
+ DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 16);
+ }
+ else if (hdma->Instance == DMA2_Channel6)
+ {
+ /*Reset request selection for DMA2 Channel6*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C6S;
+
+ /* Configure request selection for DMA2 Channel6 */
+ DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 20);
+ }
+ else if (hdma->Instance == DMA2_Channel7)
+ {
+ /*Reset request selection for DMA2 Channel7*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C7S;
+
+ /* Configure request selection for DMA2 Channel7 */
+ DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << 24);
+ }
+ }
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the DMA state*/
+ hdma->State = HAL_DMA_STATE_READY;
+
+ 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(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ /* Check the DMA peripheral state */
+ if(hdma->State == HAL_DMA_STATE_BUSY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the selected DMA Channelx */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Reset DMA Channel control register */
+ hdma->Instance->CCR = 0;
+
+ /* Reset DMA Channel Number of Data to Transfer register */
+ hdma->Instance->CNDTR = 0;
+
+ /* Reset DMA Channel peripheral address register */
+ hdma->Instance->CPAR = 0;
+
+ /* Reset DMA Channel memory address register */
+ hdma->Instance->CMAR = 0;
+
+ /* Clear all flags */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_GI_FLAG_INDEX(hdma));
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+
+ /* Reset DMA channel selection register */
+ if (hdma->Instance == DMA1_Channel1)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C1S;
+ }
+ else if (hdma->Instance == DMA1_Channel2)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C2S;
+ }
+ else if (hdma->Instance == DMA1_Channel3)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C3S;
+ }
+ else if (hdma->Instance == DMA1_Channel4)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C4S;
+ }
+ else if (hdma->Instance == DMA1_Channel5)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C5S;
+ }
+ else if (hdma->Instance == DMA1_Channel6)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C6S;
+ }
+ else if (hdma->Instance == DMA1_Channel7)
+ {
+ /*Reset DMA request*/
+ DMA1_CSELR->CSELR &= ~DMA_CSELR_C7S;
+ }
+ else if (hdma->Instance == DMA2_Channel1)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C1S;
+ }
+ else if (hdma->Instance == DMA2_Channel2)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C2S;
+ }
+ else if (hdma->Instance == DMA2_Channel3)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C3S;
+ }
+ else if (hdma->Instance == DMA2_Channel4)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C4S;
+ }
+ else if (hdma->Instance == DMA2_Channel5)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C5S;
+ }
+ else if (hdma->Instance == DMA2_Channel6)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C6S;
+ }
+ else if (hdma->Instance == DMA2_Channel7)
+ {
+ /*Reset DMA request*/
+ DMA2_CSELR->CSELR &= ~DMA_CSELR_C7S;
+ }
+
+ /* 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)
+{
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+
+ /* Disable the peripheral */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Configure the source, destination address and the data length */
+ DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ /* Enable the Peripheral */
+ __HAL_DMA_ENABLE(hdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+
+ /* Disable the peripheral */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Configure the source, destination address and the data length */
+ DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ /* Enable the transfer complete interrupt */
+ /* Enable the Half transfer complete interrupt */
+ /* Enable the transfer Error interrupt */
+ __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
+
+ /* Enable the Peripheral */
+ __HAL_DMA_ENABLE(hdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort the DMA Transfer.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Channel.
+ *
+ * @note After disabling a DMA Channel, a check for wait until the DMA Channel is
+ * effectively disabled is added. If a Channel is disabled
+ * while a data transfer is ongoing, the current data will be transferred
+ * and the Channel will be effectively disabled only after the transfer of
+ * this single data is finished.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+
+ /* Disable the channel */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the DMA Channel is effectively disabled */
+ while((hdma->Instance->CCR & DMA_CCR_EN) != 0)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @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, uint32_t CompleteLevel, uint32_t Timeout)
+{
+ uint32_t temp;
+ uint32_t tickstart = 0;
+
+ /* Get the level transfer complete flag */
+ if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
+ {
+ /* Transfer Complete flag */
+ temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma);
+ }
+ else
+ {
+ /* Half Transfer Complete flag */
+ temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma);
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET)
+ {
+ if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET))
+ {
+ /* Clear the transfer error flags */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
+
+ /* Update error code */
+ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
+
+ /* Change the DMA state */
+ hdma->State= HAL_DMA_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
+ {
+ /* Clear the transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(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 */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+
+ hdma->State = HAL_DMA_STATE_READY_HALF;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma);
+
+ 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)
+{
+ /* Transfer Error Interrupt management ***************************************/
+ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET)
+ {
+ /* Disable the transfer error interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE);
+
+ /* Clear the transfer error flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
+
+ /* 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);
+ }
+ }
+ }
+
+ /* Half Transfer Complete Interrupt management ******************************/
+ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET)
+ {
+ /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
+ if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
+ {
+ /* Disable the half transfer interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
+ }
+ /* Clear the half transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_HALF;
+
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Half transfer callback */
+ hdma->XferHalfCpltCallback(hdma);
+ }
+ }
+ }
+
+ /* Transfer Complete Interrupt management ***********************************/
+ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET)
+ {
+ if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
+ {
+ /* Disable the transfer complete interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC);
+ }
+ /* Clear the transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_NONE;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if(hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete callback */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @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 hande 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)
+{
+ /* Configure DMA Channel data length */
+ hdma->Instance->CNDTR = DataLength;
+
+ /* Peripheral to Memory */
+ 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;
+ }
+ /* Memory to Peripheral */
+ else
+ {
+ /* Configure DMA Channel source address */
+ hdma->Instance->CPAR = SrcAddress;
+
+ /* Configure DMA Channel destination address */
+ hdma->Instance->CMAR = DstAddress;
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_flash.c b/stmhal/hal/l4/src/stm32l4xx_hal_flash.c
new file mode 100644
index 000000000..d7c837b26
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_flash.c
@@ -0,0 +1,773 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_flash.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the internal FLASH memory:
+ * + Program operations functions
+ * + Memory Control functions
+ * + Peripheral Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### FLASH peripheral features #####
+ ==============================================================================
+
+ [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
+ to the Flash memory. It implements the erase and program Flash memory operations
+ and the read and write protection mechanisms.
+
+ [..] The Flash memory interface accelerates code execution with a system of instruction
+ prefetch and cache lines.
+
+ [..] The FLASH main features are:
+ (+) Flash memory read operations
+ (+) Flash memory program/erase operations
+ (+) Read / write protections
+ (+) Option bytes programming
+ (+) Prefetch on I-Code
+ (+) 32 cache lines of 4*64 bits on I-Code
+ (+) 8 cache lines of 4*64 bits on D-Code
+ (+) Error code correction (ECC) : Data in flash are 72-bits word
+ (8 bits added per double word)
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver provides functions and macros to configure and program the FLASH
+ memory of all STM32L4xx devices.
+
+ (#) Flash Memory IO Programming functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Program functions: double word and fast program (full row programming)
+ (++) There Two modes of programming :
+ (+++) Polling mode using HAL_FLASH_Program() function
+ (+++) Interrupt mode using HAL_FLASH_Program_IT() function
+
+ (#) Interrupts and flags management functions :
+ (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
+ (++) Callback functions are called when the flash operations are finished :
+ HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
+ HAL_FLASH_OperationErrorCallback()
+ (++) Get error flag status by calling HAL_GetError()
+
+ (#) Option bytes management functions :
+ (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
+ HAL_FLASH_OB_Lock() functions
+ (++) Launch the reload of the option bytes using HAL_FLASH_Launch() function.
+ In this case, a reset is generated
+
+ [..]
+ In addition to these functions, this driver includes a set of macros allowing
+ to handle the following operations:
+ (+) Set the latency
+ (+) Enable/Disable the prefetch buffer
+ (+) Enable/Disable the Instruction cache and the Data cache
+ (+) Reset the Instruction cache and the Data cache
+ (+) Enable/Disable the Flash power-down during low-power run and sleep modes
+ (+) Enable/Disable the Flash interrupts
+ (+) Monitor the Flash flags status
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASH FLASH
+ * @brief FLASH HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup FLASH_Private_Variables FLASH Private Variables
+ * @{
+ */
+/**
+ * @brief Variable used for Program/Erase sectors under interruption
+ */
+FLASH_ProcessTypeDef pFlash;
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASH_Private_Functions FLASH Private Functions
+ * @{
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
+extern void FLASH_PageErase(uint32_t Page, uint32_t Banks);
+extern void FLASH_FlushCaches(void);
+static void FLASH_SetErrorCode(void);
+static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
+static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup FLASH_Exported_Functions FLASH Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
+ * @brief Programming operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Programming operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the FLASH
+ program operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Program double word or fast program of a row at a specified address.
+ * @param TypeProgram: Indicate the way to program at a specified address.
+ * This parameter can be a value of @ref FLASH_Type_Program
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed
+ * This parameter is the data for the double word program and the address where
+ * are stored the data for the row fast program
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+ uint32_t prog_bit = 0;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
+ {
+ /* Program double-word (64-bit) at a specified address */
+ FLASH_Program_DoubleWord(Address, Data);
+ prog_bit = FLASH_CR_PG;
+ }
+ else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST))
+ {
+ /* Fast program a 32 row double-word (64-bit) at a specified address */
+ FLASH_Program_Fast(Address, (uint32_t)Data);
+
+ /* If it is the last row, the bit will be cleared at the end of the operation */
+ if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)
+ {
+ prog_bit = FLASH_CR_FSTPG;
+ }
+ }
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the program operation is completed, disable the PG or FSTPG Bit */
+ if (prog_bit != 0)
+ {
+ CLEAR_BIT(FLASH->CR, prog_bit);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Program double word or fast program of a row at a specified address with interrupt enabled.
+ * @param TypeProgram: Indicate the way to program at a specified address.
+ * This parameter can be a value of @ref FLASH_Type_Program
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed
+ * This parameter is the data for the double word program and the address where
+ * are stored the data for the row fast program
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Set internal variables used by the IRQ handler */
+ if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_LAST;
+ }
+ else
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM;
+ }
+ pFlash.Address = Address;
+
+ /* Enable End of Operation and Error interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
+
+ if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
+ {
+ /* Program double-word (64-bit) at a specified address */
+ FLASH_Program_DoubleWord(Address, Data);
+ }
+ else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST))
+ {
+ /* Fast program a 32 row double-word (64-bit) at a specified address */
+ FLASH_Program_Fast(Address, (uint32_t)Data);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handle FLASH interrupt request.
+ * @retval None
+ */
+void HAL_FLASH_IRQHandler(void)
+{
+ uint32_t tmp_page;
+
+ /* If the operation is completed, disable the PG, PNB, MER1, MER2 and PER Bit */
+ CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_PER | FLASH_CR_PNB));
+ CLEAR_BIT(FLASH->CR, FLASH_CR_MER2);
+
+ /* Disable the FSTPG Bit only if it is the last row programmed */
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST)
+ {
+ CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG);
+ }
+
+ /* Check FLASH operation error flags */
+ if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)))
+ {
+ /*Save the error code*/
+ FLASH_SetErrorCode();
+
+ /* FLASH error interrupt user callback */
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE)
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Page);
+ }
+ else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASS_ERASE)
+ {
+ HAL_FLASH_EndOfOperationCallback(pFlash.Bank);
+ }
+ else if((pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM) ||
+ (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST))
+ {
+ HAL_FLASH_OperationErrorCallback(pFlash.Address);
+ }
+
+ HAL_FLASH_OperationErrorCallback(pFlash.Address);
+
+ /*Stop the procedure ongoing*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+
+ /* Check FLASH End of Operation flag */
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE)
+ {
+ /* Nb of pages to erased can be decreased */
+ pFlash.NbPagesToErase--;
+
+ /* Check if there are still pages to erase*/
+ if(pFlash.NbPagesToErase != 0)
+ {
+ /* Indicate user which page has been erased*/
+ HAL_FLASH_EndOfOperationCallback(pFlash.Page);
+
+ /* Increment page number */
+ pFlash.Page++;
+ tmp_page = pFlash.Page;
+ FLASH_PageErase(tmp_page, pFlash.Bank);
+ }
+ else
+ {
+ /* No more pages to Erase */
+ /* Reset Address and stop Erase pages procedure */
+ pFlash.Page = 0xFFFFFFFF;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+
+ /* Flush the caches to be sure of the data consistency */
+ FLASH_FlushCaches() ;
+
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Page);
+ }
+ }
+ else
+ {
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_MASS_ERASE)
+ {
+ /* MassErase ended. Return the selected bank */
+ /* Flush the caches to be sure of the data consistency */
+ FLASH_FlushCaches() ;
+
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Bank);
+ }
+ else if((pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM) ||
+ (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST))
+ {
+ /* Program ended. Return the selected address */
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ }
+
+ /*Clear the procedure ongoing*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+ }
+
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
+ {
+ /* Disable End of Operation and Error interrupts */
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+}
+
+/**
+ * @brief FLASH end of operation interrupt callback.
+ * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure
+ * Mass Erase: Bank number which has been requested to erase
+ * Page Erase: Page which has been erased
+ * (if 0xFFFFFFFF, it means that all the selected pages have been erased)
+ * Program: Address which was selected for data program
+ * @retval None
+ */
+__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FLASH operation error interrupt callback.
+ * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure
+ * Mass Erase: Bank number which has been requested to erase
+ * Page Erase: Page number which returned an error
+ * Program: Address which was selected for data program
+ * @retval None
+ */
+__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_FLASH_OperationErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
+ * @brief Management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the FLASH
+ memory operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Unlock the FLASH control register access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Unlock(void)
+{
+ if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
+ {
+ /* Authorize the FLASH Registers access */
+ WRITE_REG(FLASH->KEYR, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR, FLASH_KEY2);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Lock the FLASH control register access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Lock(void)
+{
+ /* Set the LOCK Bit to lock the FLASH Registers access */
+ SET_BIT(FLASH->CR, FLASH_CR_LOCK);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Unlock the FLASH Option Bytes Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
+{
+ if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != RESET)
+ {
+ /* Authorizes the Option Byte register programming */
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Lock the FLASH Option Bytes Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
+{
+ /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Launch the option byte loading.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
+{
+ /* Set the bit to force the option byte reloading */
+ SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
+
+ /* Wait for last operation to be completed */
+ return(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral Errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time Errors of the FLASH peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Get the specific FLASH error flag.
+ * @retval FLASH_ErrorCode: The returned value can be:
+ * @arg HAL_FLASH_ERROR_RD: FLASH Read Protection error flag (PCROP)
+ * @arg HAL_FLASH_ERROR_PGS: FLASH Programming Sequence error flag
+ * @arg HAL_FLASH_ERROR_PGP: FLASH Programming Parallelism error flag
+ * @arg HAL_FLASH_ERROR_PGA: FLASH Programming Alignment error flag
+ * @arg HAL_FLASH_ERROR_WRP: FLASH Write protected error flag
+ * @arg HAL_FLASH_ERROR_OPERATION: FLASH operation Error flag
+ * @arg HAL_FLASH_ERROR_NONE: No error set
+ * @arg HAL_FLASH_ERROR_OP: FLASH Operation error
+ * @arg HAL_FLASH_ERROR_PROG: FLASH Programming error
+ * @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error
+ * @arg HAL_FLASH_ERROR_PGA: FLASH Programming alignment error
+ * @arg HAL_FLASH_ERROR_SIZ: FLASH Size error
+ * @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error
+ * @arg HAL_FLASH_ERROR_MIS: FLASH Fast programming data miss error
+ * @arg HAL_FLASH_ERROR_FAST: FLASH Fast programming error
+ * @arg HAL_FLASH_ERROR_RD: FLASH PCROP read error
+ * @arg HAL_FLASH_ERROR_OPTV: FLASH Option validity error
+ * @arg HAL_FLASH_ERROR_ECCD: FLASH two ECC errors have been detected
+ */
+uint32_t HAL_FLASH_GetError(void)
+{
+ return pFlash.ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @addtogroup FLASH_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Wait for a FLASH operation to complete.
+ * @param Timeout: maximum flash operation timeout
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
+{
+ /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
+ Even if the FLASH operation fails, the BUSY flag will be reset and an error
+ flag will be set */
+
+ uint32_t timeout = HAL_GetTick() + Timeout;
+
+ while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(HAL_GetTick() >= timeout)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
+ (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)))
+ {
+ /*Save the error code*/
+ FLASH_SetErrorCode();
+
+ return HAL_ERROR;
+ }
+
+ /* Check FLASH End of Operation flag */
+ if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ }
+
+ /* If there is an error flag set */
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the specific FLASH error flag.
+ * @retval None
+ */
+static void FLASH_SetErrorCode(void)
+{
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_OP;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_PROG;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_SIZ;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_PGS;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_MIS;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_FAST;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_RD;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_ECCD;
+ }
+
+ /* Clear error programming flags */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
+}
+
+/**
+ * @brief Program double-word (64-bit) at a specified address.
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed.
+ * @retval None
+ */
+static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+
+ /* Set PG bit */
+ SET_BIT(FLASH->CR, FLASH_CR_PG);
+
+ /* Program the double word */
+ *(__IO uint32_t*)Address = (uint32_t)Data;
+ *(__IO uint32_t*)(Address+4) = (uint32_t)(Data >> 32);
+}
+
+/**
+ * @brief Fast program a 32 row double-word (64-bit) at a specified address.
+ * @param Address: specifies the address to be programmed.
+ * @param DataAddress: specifies the address where the data are stored.
+ * @retval None
+ */
+static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)
+{
+ uint8_t row_index = 32;
+ __IO uint64_t *dest_addr = (__IO uint64_t*)Address;
+ __IO uint64_t *src_addr = (__IO uint64_t*)DataAddress;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
+
+ /* Set FSTPG bit */
+ SET_BIT(FLASH->CR, FLASH_CR_FSTPG);
+
+ /* Disable interrupts to avoid any interruption during the loop */
+ __disable_irq();
+
+ /* Program the 32 double word */
+ do
+ {
+ *dest_addr++ = *src_addr++;
+ } while (--row_index != 0);
+
+ /* Re-enable the interrupts */
+ __enable_irq();
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_flash_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_flash_ex.c
new file mode 100644
index 000000000..b9c5215bd
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_flash_ex.c
@@ -0,0 +1,980 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_flash_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief Extended FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the FLASH extended peripheral:
+ * + Extended programming operations functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### Flash Extended features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the FLASH interface for STM32L4xx
+ devices contains the following additional features
+
+ (+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write
+ capability (RWW)
+ (+) Dual bank memory organization
+ (+) PCROP protection for all banks
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure and program the FLASH memory
+ of all STM32L4xx devices. It includes
+ (#) Flash Memory Erase functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Erase function: Erase page, erase all sectors
+ (++) There are two modes of erase :
+ (+++) Polling Mode using HAL_FLASHEx_Erase()
+ (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
+
+ (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to :
+ (++) Set/Reset the write protection
+ (++) Set the Read protection Level
+ (++) Program the user Option Bytes
+ (++) Configure the PCROP protection
+
+ (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to :
+ (++) Get the value of a write protection area
+ (++) Know if the read protection is activated
+ (++) Get the value of the user Option Bytes
+ (++) Get the value of a PCROP area
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASHEx FLASHEx
+ * @brief FALSH Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup FLASHEx_Private_Variables FLASHEx Private Variables
+ * @{
+ */
+extern FLASH_ProcessTypeDef pFlash;
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
+ * @{
+ */
+extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
+void FLASH_PageErase(uint32_t Page, uint32_t Banks);
+static void FLASH_MassErase(uint32_t Banks);
+void FLASH_FlushCaches(void);
+static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
+static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel);
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig);
+static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr);
+static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset);
+static uint32_t FLASH_OB_GetRDP(void);
+static uint32_t FLASH_OB_GetUser(void);
+static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr);
+/**
+ * @}
+ */
+
+/* Exported functions -------------------------------------------------------*/
+/** @defgroup FLASHEx_Exported_Functions FLASH Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
+ * @brief Extended IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended programming operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the Extended FLASH
+ programming operations Operations.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory pages.
+ * @param[in] pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ *
+ * @param[out] PageError : pointer to variable that contains the configuration
+ * information on faulty page in case of error (0xFFFFFFFF means that all
+ * the pages have been correctly erased)
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+ uint32_t page_index = 0;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if (status == HAL_OK)
+ {
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /* Mass erase to be done */
+ FLASH_MassErase(pEraseInit->Banks);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the MER1 and MER2 Bits */
+ CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));
+ }
+ else
+ {
+ /*Initialization of PageError variable*/
+ *PageError = 0xFFFFFFFF;
+
+ for(page_index = pEraseInit->Page; page_index < (pEraseInit->Page + pEraseInit->NbPages); page_index++)
+ {
+ FLASH_PageErase(page_index, pEraseInit->Banks);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the PER Bit */
+ CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
+
+ if (status != HAL_OK)
+ {
+ /* In case of error, stop erase procedure and return the faulty address */
+ *PageError = page_index;
+ break;
+ }
+ }
+ }
+
+ /* Flush the caches to be sure of the data consistency */
+ FLASH_FlushCaches();
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled.
+ * @param pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Enable End of Operation and Error interrupts */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
+
+ pFlash.Bank = pEraseInit->Banks;
+
+ if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /* Mass erase to be done */
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASS_ERASE;
+ FLASH_MassErase(pEraseInit->Banks);
+ }
+ else
+ {
+ /* Erase by page to be done */
+ pFlash.ProcedureOnGoing = FLASH_PROC_PAGE_ERASE;
+ pFlash.NbPagesToErase = pEraseInit->NbPages;
+ pFlash.Page = pEraseInit->Page;
+
+ /*Erase 1st page and wait for IT */
+ FLASH_PageErase(pEraseInit->Page, pEraseInit->Banks);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Program Option bytes.
+ * @param pOBInit: pointer to an FLASH_OBInitStruct structure that
+ * contains the configuration information for the programming.
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
+
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Write protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_WRP) != RESET)
+ {
+ /* Configure of Write protection on the selected area */
+ status = FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset);
+ }
+
+ /* Read protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_RDP) != RESET)
+ {
+ /* Configure the Read protection level */
+ status = FLASH_OB_RDPConfig(pOBInit->RDPLevel);
+ }
+
+ /* User Configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_USER) != RESET)
+ {
+ /* Configure the user option bytes */
+ status = FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig);
+ }
+
+ /* PCROP Configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_PCROP) != RESET)
+ {
+ /* Configure the Proprietary code readout protection */
+ status = FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Get the Option bytes configuration.
+ * @param pOBInit: pointer to an FLASH_OBInitStruct structure that contains the
+ * configuration information. The fields pOBInit->WRPArea and
+ * pOBInit->PCROPConfig should indicate which area is requested
+ * for the WRP and PCROP
+ *
+ * @retval None
+ */
+void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ pOBInit->OptionType = (OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER | OPTIONBYTE_PCROP);
+
+ /* Get write protection on the selected area */
+ FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));
+
+ /* Get Read protection level */
+ pOBInit->RDPLevel = FLASH_OB_GetRDP();
+
+ /* Get the user option bytes */
+ pOBInit->USERConfig = FLASH_OB_GetUser();
+
+ /* Get the Proprietary code readout protection */
+ FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr));
+
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @addtogroup FLASHEx_Private_Functions
+ * @{
+ */
+/**
+ * @brief Mass erase of FLASH memory.
+ * @param Banks: Banks to be erased
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: Bank1 to be erased
+ * @arg FLASH_BANK_2: Bank2 to be erased
+ * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased
+ * @retval None
+ */
+static void FLASH_MassErase(uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK(Banks));
+
+ /* Set the Mass Erase Bit for the bank 1 if requested */
+ if((Banks & FLASH_BANK_1) != RESET)
+ {
+ SET_BIT(FLASH->CR, FLASH_CR_MER1);
+ }
+
+ /* Set the Mass Erase Bit for the bank 2 if requested */
+ if((Banks & FLASH_BANK_2) != RESET)
+ {
+ SET_BIT(FLASH->CR, FLASH_CR_MER2);
+ }
+
+ /* Proceed to erase all sectors */
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+}
+
+/**
+ * @brief Erase the specified FLASH memory page.
+ * @param Page: FLASH page to erase
+ * This parameter must be a value between 0 and (max number of pages in the bank - 1)
+ * @param Banks: Bank(s) where the page will be erased
+ * This parameter can be one or a combination of the following values:
+ * @arg FLASH_BANK_1: Page in bank 1 to be erased
+ * @arg FLASH_BANK_2: Page in bank 2 to be erased
+ * @retval None
+ */
+void FLASH_PageErase(uint32_t Page, uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_PAGE(Page));
+ assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));
+
+ if((Banks & FLASH_BANK_1) != RESET)
+ {
+ CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);
+ }
+ else
+ {
+ SET_BIT(FLASH->CR, FLASH_CR_BKER);
+ }
+
+ /* Proceed to erase the page */
+ MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (Page << 3));
+ SET_BIT(FLASH->CR, FLASH_CR_PER);
+ SET_BIT(FLASH->CR, FLASH_CR_STRT);
+}
+
+/**
+ * @brief Flush the instruction and data caches.
+ * @retval None
+ */
+void FLASH_FlushCaches(void)
+{
+ /* Flush instruction cache */
+ if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET)
+ {
+ /* Disable instruction cache */
+ __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+ /* Reset instruction cache */
+ __HAL_FLASH_INSTRUCTION_CACHE_RESET();
+ /* Enable instruction cache */
+ __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+ }
+
+ /* Flush data cache */
+ if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET)
+ {
+ /* Disable data cache */
+ __HAL_FLASH_DATA_CACHE_DISABLE();
+ /* Reset data cache */
+ __HAL_FLASH_DATA_CACHE_RESET();
+ /* Enable data cache */
+ __HAL_FLASH_DATA_CACHE_ENABLE();
+ }
+}
+
+/**
+ * @brief Configure the write protection of the desired pages.
+ *
+ * @note When the memory read protection level is selected (RDP level = 1),
+ * it is not possible to program or erase Flash memory if the CPU debug
+ * features are connected (JTAG or single wire) or boot code is being
+ * executed from RAM or System flash, even if WRP is not activated.
+ * @note To configure the WRP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ * @note To validate the WRP options, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ *
+ * @param WRPArea: specifies the area to be configured.
+ * This parameter can be one of the following values:
+ * @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A
+ * @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B
+ * @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A
+ * @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B
+ *
+ * @param WRPStartOffset: specifies the start page of the write protected area
+ * This parameter can be page number between 0 and (max number of pages in the bank - 1)
+ *
+ * @param WRDPEndOffset: specifies the end page of the write protected area
+ * This parameter can be page number between WRPStartOffset and (max number of pages in the bank - 1)
+ *
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_WRPAREA(WRPArea));
+ assert_param(IS_FLASH_PAGE(WRPStartOffset));
+ assert_param(IS_FLASH_PAGE(WRDPEndOffset));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Configure the write protected area */
+ if(WRPArea == OB_WRPAREA_BANK1_AREAA)
+ {
+ MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END),
+ (WRPStartOffset | (WRDPEndOffset << 16)));
+ }
+ else if(WRPArea == OB_WRPAREA_BANK1_AREAB)
+ {
+ MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END),
+ (WRPStartOffset | (WRDPEndOffset << 16)));
+ }
+ else if(WRPArea == OB_WRPAREA_BANK2_AREAA)
+ {
+ MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END),
+ (WRPStartOffset | (WRDPEndOffset << 16)));
+ }
+ else if(WRPArea == OB_WRPAREA_BANK2_AREAB)
+ {
+ MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END),
+ (WRPStartOffset | (WRDPEndOffset << 16)));
+ }
+
+ /* Set OPTSTRT Bit */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the option byte program operation is completed, disable the OPTSTRT Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Set the read protection level.
+ *
+ * @note To configure the RDP level, the option lock bit OPTLOCK must be
+ * cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ * @note To validate the RDP level, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ * @note !!! Warning : When enabling OB_RDP level 2 it's no more possible
+ * to go back to level 1 or 0 !!!
+ *
+ * @param RDPLevel: specifies the read protection level.
+ * This parameter can be one of the following values:
+ * @arg OB_RDP_LEVEL_0: No protection
+ * @arg OB_RDP_LEVEL_1: Read protection of the memory
+ * @arg OB_RDP_LEVEL_2: Full chip protection
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_RDP_LEVEL(RDPLevel));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Configure the RDP level in the option bytes register */
+ MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, RDPLevel);
+
+ /* Set OPTSTRT Bit */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the option byte program operation is completed, disable the OPTSTRT Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Program the FLASH User Option Byte.
+ *
+ * @note To configure the user option bytes, the option lock bit OPTLOCK must
+ * be cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ * @note To validate the user option bytes, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ *
+ * @param UserType: The FLASH User Option Bytes to be modified
+ * @param UserConfig: The FLASH User Option Bytes values:
+ * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), IWDG_SW(Bit16),
+ * IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), BFB2(Bit20),
+ * DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25).
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig)
+{
+ uint32_t optr_reg_val = 0;
+ uint32_t optr_reg_mask = 0;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_USER_TYPE(UserType));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ if((UserType & OB_USER_BOR_LEV) != RESET)
+ {
+ /* BOR level option byte should be modified */
+ assert_param(IS_OB_USER_BOR_LEVEL(UserConfig & FLASH_OPTR_BOR_LEV));
+
+ /* Set value and mask for BOR level option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_BOR_LEV);
+ optr_reg_mask |= FLASH_OPTR_BOR_LEV;
+ }
+
+ if((UserType & OB_USER_nRST_STOP) != RESET)
+ {
+ /* nRST_STOP option byte should be modified */
+ assert_param(IS_OB_USER_STOP(UserConfig & FLASH_OPTR_nRST_STOP));
+
+ /* Set value and mask for nRST_STOP option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STOP);
+ optr_reg_mask |= FLASH_OPTR_nRST_STOP;
+ }
+
+ if((UserType & OB_USER_nRST_STDBY) != RESET)
+ {
+ /* nRST_STDBY option byte should be modified */
+ assert_param(IS_OB_USER_STANDBY(UserConfig & FLASH_OPTR_nRST_STDBY));
+
+ /* Set value and mask for nRST_STDBY option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STDBY);
+ optr_reg_mask |= FLASH_OPTR_nRST_STDBY;
+ }
+
+ if((UserType & OB_USER_nRST_SHDW) != RESET)
+ {
+ /* nRST_SHDW option byte should be modified */
+ assert_param(IS_OB_USER_SHUTDOWN(UserConfig & FLASH_OPTR_nRST_SHDW));
+
+ /* Set value and mask for nRST_SHDW option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_SHDW);
+ optr_reg_mask |= FLASH_OPTR_nRST_SHDW;
+ }
+
+ if((UserType & OB_USER_IWDG_SW) != RESET)
+ {
+ /* IWDG_SW option byte should be modified */
+ assert_param(IS_OB_USER_IWDG(UserConfig & FLASH_OPTR_IWDG_SW));
+
+ /* Set value and mask for IWDG_SW option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_SW);
+ optr_reg_mask |= FLASH_OPTR_IWDG_SW;
+ }
+
+ if((UserType & OB_USER_IWDG_STOP) != RESET)
+ {
+ /* IWDG_STOP option byte should be modified */
+ assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTR_IWDG_STOP));
+
+ /* Set value and mask for IWDG_STOP option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STOP);
+ optr_reg_mask |= FLASH_OPTR_IWDG_STOP;
+ }
+
+ if((UserType & OB_USER_IWDG_STDBY) != RESET)
+ {
+ /* IWDG_STDBY option byte should be modified */
+ assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTR_IWDG_STDBY));
+
+ /* Set value and mask for IWDG_STDBY option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STDBY);
+ optr_reg_mask |= FLASH_OPTR_IWDG_STDBY;
+ }
+
+ if((UserType & OB_USER_WWDG_SW) != RESET)
+ {
+ /* WWDG_SW option byte should be modified */
+ assert_param(IS_OB_USER_WWDG(UserConfig & FLASH_OPTR_WWDG_SW));
+
+ /* Set value and mask for WWDG_SW option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_WWDG_SW);
+ optr_reg_mask |= FLASH_OPTR_WWDG_SW;
+ }
+
+ if((UserType & OB_USER_BFB2) != RESET)
+ {
+ /* BFB2 option byte should be modified */
+ assert_param(IS_OB_USER_BFB2(UserConfig & FLASH_OPTR_BFB2));
+
+ /* Set value and mask for BFB2 option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_BFB2);
+ optr_reg_mask |= FLASH_OPTR_BFB2;
+ }
+
+ if((UserType & OB_USER_DUALBANK) != RESET)
+ {
+ /* DUALBANK option byte should be modified */
+ assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DUALBANK));
+
+ /* Set value and mask for DUALBANK option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_DUALBANK);
+ optr_reg_mask |= FLASH_OPTR_DUALBANK;
+ }
+
+ if((UserType & OB_USER_nBOOT1) != RESET)
+ {
+ /* nBOOT1 option byte should be modified */
+ assert_param(IS_OB_USER_BOOT1(UserConfig & FLASH_OPTR_nBOOT1));
+
+ /* Set value and mask for nBOOT1 option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT1);
+ optr_reg_mask |= FLASH_OPTR_nBOOT1;
+ }
+
+ if((UserType & OB_USER_SRAM2_PE) != RESET)
+ {
+ /* SRAM2_PE option byte should be modified */
+ assert_param(IS_OB_USER_SRAM2_PARITY(UserConfig & FLASH_OPTR_SRAM2_PE));
+
+ /* Set value and mask for SRAM2_PE option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_PE);
+ optr_reg_mask |= FLASH_OPTR_SRAM2_PE;
+ }
+
+ if((UserType & OB_USER_SRAM2_RST) != RESET)
+ {
+ /* SRAM2_RST option byte should be modified */
+ assert_param(IS_OB_USER_SRAM2_RST(UserConfig & FLASH_OPTR_SRAM2_RST));
+
+ /* Set value and mask for SRAM2_RST option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_RST);
+ optr_reg_mask |= FLASH_OPTR_SRAM2_RST;
+ }
+
+ /* Configure the option bytes register */
+ MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val);
+
+ /* Set OPTSTRT Bit */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the option byte program operation is completed, disable the OPTSTRT Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Configure the Proprietary code readout protection of the desired addresses.
+ *
+ * @note To configure the PCROP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ * @note To validate the PCROP options, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ *
+ * @param PCROPConfig: specifies the configuration (Bank to be configured and PCROP_RDP option).
+ * This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2
+ * with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE
+ *
+ * @param PCROPStartAddr: specifies the start address of the Proprietary code readout protection
+ * This parameter can be an address between begin and end of the bank
+ *
+ * @param PCROPEndAddr: specifies the end address of the Proprietary code readout protection
+ * This parameter can be an address between PCROPStartAddr and end of the bank
+ *
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t reg_value = 0;
+ uint32_t bank1_addr, bank2_addr;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK_EXCLUSIVE(PCROPConfig & FLASH_BANK_BOTH));
+ assert_param(IS_OB_PCROP_RDP(PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPStartAddr));
+ assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPEndAddr));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Get the information about the bank swapping */
+ if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0)
+ {
+ bank1_addr = FLASH_BASE;
+ bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;
+ }
+ else
+ {
+ bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;
+ bank2_addr = FLASH_BASE;
+ }
+
+ /* Configure the Proprietary code readout protection */
+ if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1)
+ {
+ reg_value = ((PCROPStartAddr - bank1_addr) >> 3);
+ MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);
+
+ reg_value = ((PCROPEndAddr - bank1_addr) >> 3);
+ MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);
+ }
+ else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2)
+ {
+ reg_value = ((PCROPStartAddr - bank2_addr) >> 3);
+ MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);
+
+ reg_value = ((PCROPEndAddr - bank2_addr) >> 3);
+ MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);
+ }
+
+ MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP_RDP, (PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));
+
+ /* Set OPTSTRT Bit */
+ SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the option byte program operation is completed, disable the OPTSTRT Bit */
+ CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Return the FLASH Write Protection Option Bytes value.
+ *
+ * @param[in] WRPArea: specifies the area to be returned.
+ * This parameter can be one of the following values:
+ * @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A
+ * @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B
+ * @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A
+ * @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B
+ *
+ * @param[out] WRPStartOffset: specifies the address where to copied the start page
+ * of the write protected area
+ *
+ * @param[out] WRDPEndOffset: specifies the address where to copied the end page of
+ * the write protected area
+ *
+ * @retval None
+ */
+static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_WRPAREA(WRPArea));
+
+ /* Get the configuration of the write protected area */
+ if(WRPArea == OB_WRPAREA_BANK1_AREAA)
+ {
+ *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
+ *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> 16);
+ }
+ else if(WRPArea == OB_WRPAREA_BANK1_AREAB)
+ {
+ *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
+ *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> 16);
+ }
+ else if(WRPArea == OB_WRPAREA_BANK2_AREAA)
+ {
+ *WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT);
+ *WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> 16);
+ }
+ else if(WRPArea == OB_WRPAREA_BANK2_AREAB)
+ {
+ *WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT);
+ *WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> 16);
+ }
+}
+
+/**
+ * @brief Return the FLASH Read Protection level.
+ * @retval FLASH ReadOut Protection Status:
+ * This return value can be one of the following values:
+ * @arg OB_RDP_LEVEL_0: No protection
+ * @arg OB_RDP_LEVEL_1: Read protection of the memory
+ * @arg OB_RDP_LEVEL_2: Full chip protection
+ */
+static uint32_t FLASH_OB_GetRDP(void)
+{
+ if ((READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP) != OB_RDP_LEVEL_0) &&
+ (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP) != OB_RDP_LEVEL_2))
+ {
+ return (OB_RDP_LEVEL_1);
+ }
+ else
+ {
+ return (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP));
+ }
+}
+
+/**
+ * @brief Return the FLASH User Option Byte value.
+ * @retval The FLASH User Option Bytes values:
+ * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14),
+ * IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19),
+ * BFB2(Bit20), DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25).
+ */
+static uint32_t FLASH_OB_GetUser(void)
+{
+ uint32_t user_config = READ_REG(FLASH->OPTR);
+ CLEAR_BIT(user_config, FLASH_OPTR_RDP);
+
+ return user_config;
+}
+
+/**
+ * @brief Return the FLASH Write Protection Option Bytes value.
+ *
+ * @param PCROPConfig [inout]: specifies the configuration (Bank to be configured and PCROP_RDP option).
+ * This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2
+ * with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE
+ *
+ * @param PCROPStartAddr [out]: specifies the address where to copied the start address
+ * of the Proprietary code readout protection
+ *
+ * @param PCROPEndAddr [out]: specifies the address where to copied the end address of
+ * the Proprietary code readout protection
+ *
+ * @retval None
+ */
+static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr)
+{
+ uint32_t reg_value = 0;
+ uint32_t bank1_addr, bank2_addr;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK_EXCLUSIVE((*PCROPConfig) & FLASH_BANK_BOTH));
+
+ /* Get the information about the bank swapping */
+ if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0)
+ {
+ bank1_addr = FLASH_BASE;
+ bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;
+ }
+ else
+ {
+ bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;
+ bank2_addr = FLASH_BASE;
+ }
+
+ if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1)
+ {
+ reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);
+ *PCROPStartAddr = (reg_value << 3) + bank1_addr;
+
+ reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);
+ *PCROPEndAddr = (reg_value << 3) + bank1_addr;
+ }
+ else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2)
+ {
+ reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);
+ *PCROPStartAddr = (reg_value << 3) + bank2_addr;
+
+ reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);
+ *PCROPEndAddr = (reg_value << 3) + bank2_addr;
+ }
+
+ *PCROPConfig |= (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP_RDP);
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_flash_ramfunc.c b/stmhal/hal/l4/src/stm32l4xx_hal_flash_ramfunc.c
new file mode 100644
index 000000000..1e08b9ccf
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_flash_ramfunc.c
@@ -0,0 +1,155 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_flash_ramfunc.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief FLASH RAMFUNC driver.
+ * This file provides a Flash firmware functions which should be
+ * executed from internal SRAM
+ * + FLASH HalfPage Programming
+ * + FLASH Power Down in Run mode
+ *
+ * @verbatim
+ ==============================================================================
+ ##### Flash RAM functions #####
+ ==============================================================================
+
+ *** ARM Compiler ***
+ --------------------
+ [..] RAM functions are defined using the toolchain options.
+ Functions that are executed in RAM should reside in a separate
+ source module. Using the 'Options for File' dialog you can simply change
+ the 'Code / Const' area of a module to a memory space in physical RAM.
+ Available memory areas are declared in the 'Target' tab of the
+ Options for Target' dialog.
+
+ *** ICCARM Compiler ***
+ -----------------------
+ [..] RAM functions are defined using a specific toolchain keyword "__ramfunc".
+
+ *** GNU Compiler ***
+ --------------------
+ [..] RAM functions are defined using a specific toolchain attribute
+ "__attribute__((section(".RamFunc")))".
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASH_RAMFUNC FLASH_RAMFUNC
+ * @brief FLASH functions executed from RAM
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions -------------------------------------------------------*/
+
+/** @defgroup FLASH_RAMFUNC_Exported_Functions FLASH in RAM function Exported Functions
+ * @{
+ */
+
+/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group1 Peripheral features functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### ramfunc functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions that should be executed from RAM.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the Power down in Run Mode
+ * @note This function should be called and executed from SRAM memory
+ * @retval None
+ */
+__RAM_FUNC HAL_FLASHEx_EnableRunPowerDown(void)
+{
+ /* Enable the Power Down in Run mode*/
+ __HAL_FLASH_POWER_DOWN_ENABLE();
+
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Disable the Power down in Run Mode
+ * @note This function should be called and executed from SRAM memory
+ * @retval None
+ */
+__RAM_FUNC HAL_FLASHEx_DisableRunPowerDown(void)
+{
+ /* Disable the Power Down in Run mode*/
+ __HAL_FLASH_POWER_DOWN_DISABLE();
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_gpio.c b/stmhal/hal/l4/src/stm32l4xx_hal_gpio.c
new file mode 100644
index 000000000..5c61d5fc2
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_gpio.c
@@ -0,0 +1,562 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_gpio.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @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
+ *
+ @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 39 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 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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup GPIO GPIO
+ * @brief GPIO HAL module driver
+ * @{
+ */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup GPIO_Private_Defines GPIO Private Defines
+ * @{
+ */
+#define GPIO_MODE ((uint32_t)0x00000003)
+#define ANALOG_MODE ((uint32_t)0x00000008)
+#define EXTI_MODE ((uint32_t)0x10000000)
+#define GPIO_MODE_IT ((uint32_t)0x00010000)
+#define GPIO_MODE_EVT ((uint32_t)0x00020000)
+#define RISING_EDGE ((uint32_t)0x00100000)
+#define FALLING_EDGE ((uint32_t)0x00200000)
+#define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010)
+
+#define GPIO_NUMBER ((uint32_t)16)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup GPIO_Private_Macros GPIO Private Macros
+ * @{
+ */
+/**
+ * @}
+ */
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup GPIO_Exported_Functions GPIO Exported Functions
+ * @{
+ */
+
+/** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @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 STM32L4 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 = 0x00;
+ uint32_t iocurrent = 0x00;
+ uint32_t temp = 0x00;
+
+ /* 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) != RESET)
+ {
+ /* Get current io position */
+ iocurrent = (GPIO_Init->Pin) & (1U << position);
+
+ if(iocurrent)
+ {
+ /*--------------------- GPIO Mode Configuration ------------------------*/
+ /* In case of Alternate function mode selection */
+ if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
+ {
+ /* 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 >> 3];
+ temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
+ temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
+ GPIOx->AFR[position >> 3] = temp;
+ }
+
+ /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
+ temp = GPIOx->MODER;
+ temp &= ~(GPIO_MODER_MODE0 << (position * 2));
+ temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
+ GPIOx->MODER = temp;
+
+ /* In case of Output or Alternate function mode selection */
+ if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
+ (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
+ {
+ /* Check the Speed parameter */
+ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
+ /* Configure the IO Speed */
+ temp = GPIOx->OSPEEDR;
+ temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2));
+ temp |= (GPIO_Init->Speed << (position * 2));
+ GPIOx->OSPEEDR = temp;
+
+ /* Configure the IO Output Type */
+ temp = GPIOx->OTYPER;
+ temp &= ~(GPIO_OTYPER_OT0 << position) ;
+ temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);
+ GPIOx->OTYPER = temp;
+ }
+
+ /* In case of Analog mode, check if ADC control mode is selected */
+ if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG)
+ {
+ /* Configure the IO Output Type */
+ temp = GPIOx->ASCR;
+ temp &= ~(GPIO_ASCR_ASC0 << position) ;
+ temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position);
+ GPIOx->ASCR = temp;
+ }
+
+ /* Activate the Pull-up or Pull down resistor for the current IO */
+ temp = GPIOx->PUPDR;
+ temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2));
+ temp |= ((GPIO_Init->Pull) << (position * 2));
+ GPIOx->PUPDR = temp;
+
+ /*--------------------- EXTI Mode Configuration ------------------------*/
+ /* Configure the External Interrupt or event for the current IO */
+ if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
+ {
+ /* Enable SYSCFG Clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ temp = SYSCFG->EXTICR[position >> 2];
+ temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
+ SYSCFG->EXTICR[position >> 2] = temp;
+
+ /* Clear EXTI line configuration */
+ temp = EXTI->IMR1;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->IMR1 = temp;
+
+ temp = EXTI->EMR1;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->EMR1 = temp;
+
+ /* Clear Rising Falling edge configuration */
+ temp = EXTI->RTSR1;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->RTSR1 = temp;
+
+ temp = EXTI->FTSR1;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->FTSR1 = 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 STM32L4 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 = 0x00;
+ uint32_t iocurrent = 0x00;
+ uint32_t tmp = 0x00;
+
+ /* 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) != RESET)
+ {
+ /* Get current io position */
+ iocurrent = (GPIO_Pin) & (1U << position);
+
+ if (iocurrent)
+ {
+ /*------------------------- GPIO Mode Configuration --------------------*/
+ /* Configure IO in Analog Mode */
+ GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2));
+
+ /* Configure the default Alternate Function in current IO */
+ GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
+
+ /* Configure the default value for IO Speed */
+ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2));
+
+ /* Configure the default value IO Output Type */
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ;
+
+ /* Deactivate the Pull-up and Pull-down resistor for the current IO */
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2));
+
+ /* Deactivate the Control bit of Analog mode for the current IO */
+ GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position);
+
+ /*------------------------- EXTI Mode Configuration --------------------*/
+ /* Clear the External Interrupt or Event for the current IO */
+
+ tmp = SYSCFG->EXTICR[position >> 2];
+ tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
+ if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
+ {
+ tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
+ SYSCFG->EXTICR[position >> 2] &= ~tmp;
+
+ /* Clear EXTI line configuration */
+ EXTI->IMR1 &= ~((uint32_t)iocurrent);
+ EXTI->EMR1 &= ~((uint32_t)iocurrent);
+
+ /* Clear Rising Falling edge configuration */
+ EXTI->RTSR1 &= ~((uint32_t)iocurrent);
+ EXTI->FTSR1 &= ~((uint32_t)iocurrent);
+ }
+ }
+
+ position++;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
+ * @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..H) to select the GPIO peripheral for STM32L4 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) != (uint32_t)GPIO_PIN_RESET)
+ {
+ 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..H) to select the GPIO peripheral for STM32L4 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 Toggle the specified GPIO pin.
+ * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family
+ * @param GPIO_Pin: specifies the pin to be toggled.
+ * @retval None
+ */
+void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ GPIOx->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 STM32L4 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 bit*/
+ tmp = GPIOx->LCKR;
+
+ if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)
+ {
+ 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) != RESET)
+ {
+ __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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_i2c.c b/stmhal/hal/l4/src/stm32l4xx_hal_i2c.c
new file mode 100644
index 000000000..7d683a4e5
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_i2c.c
@@ -0,0 +1,5227 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_i2c.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief I2C HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Inter Integrated Circuit (I2C) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The I2C HAL driver can be used as follows:
+
+ (#) Declare a I2C_HandleTypeDef handle structure, for example:
+ I2C_HandleTypeDef hi2c;
+
+ (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API:
+ (##) Enable the I2Cx interface clock
+ (##) I2C pins configuration
+ (+++) Enable the clock for the I2C GPIOs
+ (+++) Configure I2C pins as alternate function open-drain
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the I2Cx interrupt priority
+ (+++) Enable the NVIC I2C IRQ Channel
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel
+ (+++) Enable the DMAx interface clock using
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx channel
+ (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
+ the DMA Tx or Rx channel
+
+ (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode,
+ Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure.
+
+ (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware
+ (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API.
+
+ (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady()
+
+ (#) For I2C IO and IO MEM operations, three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit()
+ (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive()
+ (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit()
+ (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive()
+
+ *** Polling mode IO MEM operation ***
+ =====================================
+ [..]
+ (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write()
+ (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read()
+
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT()
+ (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Receive_IT()
+ (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Transmit_IT()
+ (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Receive_IT()
+ (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT()
+
+ *** Interrupt mode IO sequential operation ***
+ ===================================
+ [..]
+ (@) These interfaces allow to manage a sequential transfer with a repeated start condition
+ when a direction change during transfer
+ [..]
+ (+) A specific option field manage the different steps of a sequential transfer
+ (+) Option field values are defined through I2C_XferOptions_definition and are listed below:
+ (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode
+ (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address
+ and data to transfer without a final stop condition
+ (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address
+ and with new data to transfer if the direction change or manage only the new data to transfer
+ if no direction change and without a final stop condition in both cases
+ (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address
+ and with new data to transfer if the direction change or manage only the new data to transfer
+ if no direction change and with a final stop condition in both cases
+
+ (+) Differents sequential I2C interfaces are listed below:
+ (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Transmit_IT()
+ (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Receive_IT()
+ (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+++) The associated previous transfer callback is called at the end of abort process
+ (+++) mean HAL_I2C_MasterTxCpltCallback() in case of previous state was master transmit
+ (+++) mean HAL_I2c_MasterRxCpltCallback() in case of previous state was master receive
+ (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT()
+ (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can
+ add his own code to check the Address Match Code and the transmission direction request by master (Write/Read).
+ (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_ListenCpltCallback()
+ (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Transmit_IT()
+ (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Receive_IT()
+ (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+
+ *** Interrupt mode IO MEM operation ***
+ =======================================
+ [..]
+ (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using
+ HAL_I2C_Mem_Write_IT()
+ (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using
+ HAL_I2C_Mem_Read_IT()
+ (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Master_Transmit_DMA()
+ (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Master_Receive_DMA()
+ (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Slave_Transmit_DMA()
+ (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Slave_Receive_DMA()
+ (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+ *** DMA mode IO MEM operation ***
+ =================================
+ [..]
+ (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using
+ HAL_I2C_Mem_Write_DMA()
+ (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using
+ HAL_I2C_Mem_Read_DMA()
+ (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+
+ *** I2C HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in I2C HAL driver.
+
+ (+) __HAL_I2C_ENABLE: Enable the I2C peripheral
+ (+) __HAL_I2C_DISABLE: Disable the I2C peripheral
+ (+) __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not
+ (+) __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag
+ (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt
+ (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt
+
+ [..]
+ (@) You can refer to the I2C HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2C I2C
+ * @brief I2C HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup I2C_Private_Define I2C Private Define
+ * @{
+ */
+#define TIMING_CLEAR_MASK ((uint32_t)0xF0FFFFFF) /*!< I2C TIMING clear register Mask */
+#define I2C_TIMEOUT_ADDR ((uint32_t)10000) /*!< 10 s */
+#define I2C_TIMEOUT_BUSY ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_DIR ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_RXNE ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_STOPF ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_TC ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_TCR ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_TXIS ((uint32_t)25) /*!< 25 ms */
+#define I2C_TIMEOUT_FLAG ((uint32_t)25) /*!< 25 ms */
+
+#define SlaveAddr_SHIFT 7
+#define SlaveAddr_MSK 0x06
+
+/* Private define for @ref PreviousState usage */
+#define I2C_STATE_MSK ((uint32_t)((HAL_I2C_STATE_BUSY_TX | HAL_I2C_STATE_BUSY_RX) & (~HAL_I2C_STATE_READY))) /*!< Mask State define, keep only RX and TX bits */
+#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */
+#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MEM_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MEM)) /*!< Memory Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MEM_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MEM)) /*!< Memory Busy RX, combinaison of State LSB and Mode enum */
+
+
+/* Private define to centralize the enable/disable of Interrupts */
+#define I2C_XFER_TX_IT ((uint32_t)0x00000001)
+#define I2C_XFER_RX_IT ((uint32_t)0x00000002)
+#define I2C_XFER_LISTEN_IT ((uint32_t)0x00000004)
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup I2C_Private_Functions I2C Private Functions
+ * @{
+ */
+static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAMemTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAMemReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAError(DMA_HandleTypeDef *hdma);
+
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart);
+
+static HAL_StatusTypeDef I2C_Master_ISR(I2C_HandleTypeDef *hi2c);
+static HAL_StatusTypeDef I2C_Slave_ISR(I2C_HandleTypeDef *hi2c);
+
+static HAL_StatusTypeDef I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest);
+static HAL_StatusTypeDef I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest);
+
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup I2C_Exported_Functions I2C Exported Functions
+ * @{
+ */
+
+/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ deinitialize the I2Cx peripheral:
+
+ (+) User must Implement HAL_I2C_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_I2C_Init() to configure the selected device with
+ the selected configuration:
+ (++) Clock Timing
+ (++) Own Address 1
+ (++) Addressing mode (Master, Slave)
+ (++) Dual Addressing mode
+ (++) Own Address 2
+ (++) Own Address 2 Mask
+ (++) General call mode
+ (++) Nostretch mode
+
+ (+) Call the function HAL_I2C_DeInit() to restore the default configuration
+ of the selected I2Cx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the I2C according to the specified parameters
+ * in the I2C_InitTypeDef and initialize the associated handle.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the I2C handle allocation */
+ if(hi2c == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1));
+ assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode));
+ assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode));
+ assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2));
+ assert_param(IS_I2C_OWN_ADDRESS2_MASK(hi2c->Init.OwnAddress2Masks));
+ assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode));
+ assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode));
+
+ if(hi2c->State == HAL_I2C_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hi2c->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_I2C_MspInit(hi2c);
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /*---------------------------- I2Cx TIMINGR Configuration ------------------*/
+ /* Configure I2Cx: Frequency range */
+ hi2c->Instance->TIMINGR = hi2c->Init.Timing & TIMING_CLEAR_MASK;
+
+ /*---------------------------- I2Cx OAR1 Configuration ---------------------*/
+ /* Configure I2Cx: Own Address1 and ack own address1 mode */
+ hi2c->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
+ if(hi2c->Init.OwnAddress1 != 0)
+ {
+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT)
+ {
+ hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | hi2c->Init.OwnAddress1);
+ }
+ else /* I2C_ADDRESSINGMODE_10BIT */
+ {
+ hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hi2c->Init.OwnAddress1);
+ }
+ }
+
+ /*---------------------------- I2Cx CR2 Configuration ----------------------*/
+ /* Configure I2Cx: Addressing Master mode */
+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ hi2c->Instance->CR2 = (I2C_CR2_ADD10);
+ }
+ /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
+ hi2c->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
+
+ /*---------------------------- I2Cx OAR2 Configuration ---------------------*/
+ /* Configure I2Cx: Dual mode and Own Address2 */
+ hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2 | (hi2c->Init.OwnAddress2Masks << 8));
+
+ /*---------------------------- I2Cx CR1 Configuration ----------------------*/
+ /* Configure I2Cx: Generalcall and NoStretch mode */
+ hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode);
+
+ /* Enable the selected I2C peripheral */
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the I2C peripheral.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the I2C handle allocation */
+ if(hi2c == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the I2C Peripheral Clock */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_I2C_MspDeInit(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_RESET;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the I2C MSP.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the I2C MSP.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Exported_Functions_Group2 Input and Output operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the I2C data
+ transfers.
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode : The communication is performed in the polling mode.
+ The status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode : The communication is performed using Interrupts
+ or DMA. These functions return the status of the transfer startup.
+ The end of the data processing will be indicated through the
+ dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (#) Blocking mode functions are :
+ (++) HAL_I2C_Master_Transmit()
+ (++) HAL_I2C_Master_Receive()
+ (++) HAL_I2C_Slave_Transmit()
+ (++) HAL_I2C_Slave_Receive()
+ (++) HAL_I2C_Mem_Write()
+ (++) HAL_I2C_Mem_Read()
+ (++) HAL_I2C_IsDeviceReady()
+
+ (#) No-Blocking mode functions with Interrupt are :
+ (++) HAL_I2C_Master_Transmit_IT()
+ (++) HAL_I2C_Master_Receive_IT()
+ (++) HAL_I2C_Slave_Transmit_IT()
+ (++) HAL_I2C_Slave_Receive_IT()
+ (++) HAL_I2C_Mem_Write_IT()
+ (++) HAL_I2C_Mem_Read_IT()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_I2C_Master_Transmit_DMA()
+ (++) HAL_I2C_Master_Receive_DMA()
+ (++) HAL_I2C_Slave_Transmit_DMA()
+ (++) HAL_I2C_Slave_Receive_DMA()
+ (++) HAL_I2C_Mem_Write_DMA()
+ (++) HAL_I2C_Mem_Read_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_I2C_MemTxCpltCallback()
+ (++) HAL_I2C_MemRxCpltCallback()
+ (++) HAL_I2C_MasterTxCpltCallback()
+ (++) HAL_I2C_MasterRxCpltCallback()
+ (++) HAL_I2C_SlaveTxCpltCallback()
+ (++) HAL_I2C_SlaveRxCpltCallback()
+ (++) HAL_I2C_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmits in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+ uint32_t sizetmp = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ /* Size > 255, need to set RELOAD bit */
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+ sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
+ sizetmp = Size;
+ }
+
+ do
+ {
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*pData++);
+ sizetmp--;
+ Size--;
+
+ if((sizetmp == 0)&&(Size!=0))
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ sizetmp = Size;
+ }
+ }
+
+ }while(Size > 0);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receives in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+ uint32_t sizetmp = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ /* Size > 255, need to set RELOAD bit */
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ sizetmp = Size;
+ }
+
+ do
+ {
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Write data to RXDR */
+ (*pData++) =hi2c->Instance->RXDR;
+ sizetmp--;
+ Size--;
+
+ if((sizetmp == 0)&&(Size!=0))
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ sizetmp = Size;
+ }
+ }
+
+ }while(Size > 0);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmits in slave mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Wait until ADDR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+
+ /* If 10bit addressing mode is selected */
+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ /* Wait until ADDR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+ }
+
+ /* Wait until DIR flag is set Transmitter mode */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ do
+ {
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*pData++);
+ Size--;
+ }while(Size > 0);
+
+ /* Wait until STOP flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Normal use case for Transmitter mode */
+ /* A NACK is generated to confirm the end of transfer */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_STOPF);
+
+ /* Wait until BUSY flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in blocking mode
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Wait until ADDR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+
+ /* Wait until DIR flag is reset Receiver mode */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ while(Size > 0)
+ {
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Store Last receive data if any */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ (*pData++) = hi2c->Instance->RXDR;
+ }
+
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /* Read data from RXDR */
+ (*pData++) = hi2c->Instance->RXDR;
+ Size--;
+ }
+
+ /* Wait until STOP flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_STOPF);
+
+ /* Wait until BUSY flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
+{
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
+{
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferSize = Size;
+ hi2c->XferCount = Size;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferSize = Size;
+ hi2c->XferCount = Size;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if((hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
+ }
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, I2C_TIMEOUT_TXIS, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Abort DMA */
+ HAL_DMA_Abort(hi2c->hdmatx);
+
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize);
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ }
+
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, tickstart) != HAL_OK)
+ {
+ /* Abort DMA */
+ HAL_DMA_Abort(hi2c->hdmarx);
+
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = Size;
+
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Wait until ADDR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, I2C_TIMEOUT_ADDR, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+
+ /* If 10bits addressing mode is selected */
+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ /* Wait until ADDR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, I2C_TIMEOUT_ADDR, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+ }
+
+ /* Wait until DIR flag is set Transmitter mode */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, RESET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferSize = Size;
+ hi2c->XferCount = Size;
+
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, Size);
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Wait until ADDR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, I2C_TIMEOUT_ADDR, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+
+ /* Wait until DIR flag is set Receiver mode */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, I2C_TIMEOUT_DIR, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in blocking mode to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+ uint32_t Sizetmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set NBYTES to write and reload if size > 255 */
+ /* Size > 255, need to set RELOAD bit */
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ Sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ Sizetmp = Size;
+ }
+
+ do
+ {
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Write data to DR */
+ hi2c->Instance->TXDR = (*pData++);
+ Sizetmp--;
+ Size--;
+
+ if((Sizetmp == 0)&&(Size!=0))
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ Sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ Sizetmp = Size;
+ }
+ }
+
+ }while(Size > 0);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in blocking mode from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+ uint32_t Sizetmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ /* Size > 255, need to set RELOAD bit */
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ Sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ Sizetmp = Size;
+ }
+
+ do
+ {
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Read data from RXDR */
+ (*pData++) = hi2c->Instance->RXDR;
+
+ /* Decrement the Size counter */
+ Sizetmp--;
+ Size--;
+
+ if((Sizetmp == 0)&&(Size!=0))
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if(Size > 255)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ Sizetmp = 255;
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ Sizetmp = Size;
+ }
+ }
+
+ }while(Size > 0);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set NBYTES to write and reload if size > 255 */
+ /* Size > 255, need to set RELOAD bit */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ /* Size > 255, need to set RELOAD bit */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMemTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, I2C_TIMEOUT_TXIS, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMemReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize);
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ }
+
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, I2C_TIMEOUT_RXNE, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Checks if target device is ready for communication.
+ * @note This function is used with Memory devices
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param Trials Number of trials
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ __IO uint32_t I2C_Trials = 0;
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ do
+ {
+ /* Generate Start */
+ hi2c->Instance->CR2 = I2C_GENERATE_START(hi2c->Init.AddressingMode,DevAddress);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set or a NACK flag is set*/
+ tickstart = HAL_GetTick();
+ while((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) && (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET) && (hi2c->State != HAL_I2C_STATE_TIMEOUT))
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* Device is ready */
+ hi2c->State = HAL_I2C_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check if the NACKF flag has not been set */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET)
+ {
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Device is ready */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Clear STOP Flag, auto generated with autoend*/
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ /* Check if the maximum allowed number of trials has been reached */
+ if (I2C_Trials++ == Trials)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+ }while(I2C_Trials < Trials);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with Interrupt.
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if((hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ /* If transfer direction not change, do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if(hi2c->PreviousState == I2C_STATE_SLAVE_BUSY_TX)
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, hi2c->XferOptions, I2C_NO_STARTSTOP);
+ }
+ /* Else transfer direction change, so generate Restart with new transfer direction */
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, hi2c->XferOptions, I2C_GENERATE_START_WRITE);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+
+ if(Size > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = Size;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 and generate RESTART */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ /* If transfer direction not change, do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX)
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, hi2c->XferOptions, I2C_NO_STARTSTOP);
+ }
+ /* Else transfer direction change, so generate Restart with new transfer direction */
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, hi2c->XferOptions, I2C_GENERATE_START_READ);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if(hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferSize = Size;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+
+ if(I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE)
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if(hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferSize = Size;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+
+ if(I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT)
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable the Address listen mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c)
+{
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+
+ /* Enable the Address Match interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disable the Address listen mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ uint32_t tmp;
+
+ /* Disable Address listen mode only if a transfer is not ongoing */
+ if(hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK;
+ hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode);
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Disable the Address Match interrupt */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Abort a master/host I2C process communication with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress)
+{
+ if((hi2c->Mode == HAL_I2C_MODE_MASTER) || \
+ ((hi2c->ErrorCode != HAL_I2C_ERROR_NONE) && (hi2c->Mode == HAL_I2C_MODE_MASTER)))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Keep the same state as previous */
+ /* to perform as well the call of the corresponding end of transfer callback */
+ if((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) && (hi2c->ErrorCode != HAL_I2C_ERROR_NONE))
+ {
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ }
+ else if((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) && (hi2c->ErrorCode != HAL_I2C_ERROR_NONE))
+ {
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ }
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Set NBYTES to 1 to generate a dummy read on I2C peripheral */
+ /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
+ I2C_TransferConfig(hi2c, DevAddress, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ if((hi2c->State == HAL_I2C_STATE_BUSY_TX) && (hi2c->Mode == HAL_I2C_MODE_MASTER))
+ {
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+ if((hi2c->State == HAL_I2C_STATE_BUSY_RX) && (hi2c->Mode == HAL_I2C_MODE_MASTER))
+ {
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Wrong usage of abort function */
+ /* This function should be used only in case of abort monitored by master device */
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
+ * @{
+ */
+
+/**
+ * @brief This function handles I2C event interrupt request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
+{
+ uint32_t tmpisrvalue = 0;
+
+ /* Use a local variable to store the current ISR flags */
+ /* This action will avoid a wrong treatment due to ISR flags change during interrupt handler */
+ tmpisrvalue = I2C_GET_ISR_REG(hi2c);
+
+ /* I2C in mode Transmitter ---------------------------------------------------*/
+ if (((I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_TXIS) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_TCR) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_TC) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_STOPF) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_AF) != RESET)) && (__HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_TXI)) != RESET))
+ {
+ /* Slave mode selected */
+ if (hi2c->Mode == HAL_I2C_MODE_SLAVE)
+ {
+ I2C_Slave_ISR(hi2c);
+ }
+ /* Master or Memory mode selected */
+ else if ((hi2c->Mode == HAL_I2C_MODE_MASTER) || (hi2c->Mode == HAL_I2C_MODE_MEM))
+ {
+ I2C_Master_ISR(hi2c);
+ }
+ }
+
+ /* I2C in mode Receiver ----------------------------------------------------*/
+ if (((I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_RXNE) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_TCR) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_TC) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_STOPF) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_AF) != RESET)) && (__HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_RXI)) != RESET))
+ {
+ /* Slave mode selected */
+ if (hi2c->Mode == HAL_I2C_MODE_SLAVE)
+ {
+ I2C_Slave_ISR(hi2c);
+ }
+ /* Master or Memory mode selected */
+ else if ((hi2c->Mode == HAL_I2C_MODE_MASTER) || (hi2c->Mode == HAL_I2C_MODE_MEM))
+ {
+ I2C_Master_ISR(hi2c);
+ }
+ }
+
+ /* I2C in mode Listener Only --------------------------------------------------*/
+ if (((I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_ADDR) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_STOPF) != RESET) || (I2C_CHECK_FLAG(tmpisrvalue, I2C_FLAG_AF) != RESET)) && ((__HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_ADDRI) != RESET) || (__HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_STOPI) != RESET) || (__HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_NACKI) != RESET)))
+ {
+ if(hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ if((hi2c->State == HAL_I2C_STATE_LISTEN) || (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) || (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ I2C_Slave_ISR(hi2c);
+ }
+ }
+ else
+ {
+ if(hi2c->Mode == HAL_I2C_MODE_SLAVE)
+ {
+ I2C_Slave_ISR(hi2c);
+ }
+ }
+ }
+}
+
+/**
+ * @brief This function handles I2C error interrupt request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c)
+{
+ /* I2C Bus error interrupt occurred ------------------------------------*/
+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BERR) == SET) && (__HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_ERRI) == SET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_BERR;
+
+ /* Clear BERR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
+ }
+
+ /* I2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/
+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_OVR) == SET) && (__HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_ERRI) == SET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_OVR;
+
+ /* Clear OVR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
+ }
+
+ /* I2C Arbitration Loss error interrupt occurred -------------------------------------*/
+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ARLO) == SET) && (__HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_ERRI) == SET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO;
+
+ /* Clear ARLO flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
+ }
+
+ /* Call the Error Callback in case of Error detected */
+ if((hi2c->ErrorCode & (HAL_I2C_ERROR_BERR | HAL_I2C_ERROR_OVR | HAL_I2C_ERROR_ARLO)) != HAL_I2C_ERROR_NONE)
+ {
+ if(((hi2c->State == HAL_I2C_STATE_BUSY_TX) || (hi2c->State == HAL_I2C_STATE_BUSY_RX)) && (hi2c->Mode == HAL_I2C_MODE_SLAVE))
+ {
+ /* Reset only HAL_I2C_STATE_SLAVE_BUSY_XX */
+ /* keep HAL_I2C_STATE_LISTEN if set */
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ }
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ }
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+}
+
+/**
+ * @brief Master Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MasterTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Master Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MasterRxCpltCallback could be implemented in the user file
+ */
+}
+
+/** @brief Slave Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Address Match callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param TransferDirection: Master request Transfer Direction (Write/Read), value of @ref I2C_XferOptions_definition
+ * @param AddrMatchCode: Address Match Code
+ * @retval None
+ */
+__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+ UNUSED(TransferDirection);
+ UNUSED(AddrMatchCode);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_AddrCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Listen Complete callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_ListenCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MemTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MemRxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C error callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions
+ * @brief Peripheral State, Mode and Error functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State, Mode and Error functions #####
+ ===============================================================================
+ [..]
+ This subsection permit to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the I2C handle state.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL state
+ */
+HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c)
+{
+ /* Return I2C handle state */
+ return hi2c->State;
+}
+
+/**
+ * @brief Returns the I2C Master, Slave, Memory or no mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for I2C module
+ * @retval HAL mode
+ */
+HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->Mode;
+}
+
+/**
+* @brief Return the I2C error code.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+* @retval I2C Error Code
+*/
+uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2C_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Master_ISR(I2C_HandleTypeDef *hi2c)
+{
+ uint16_t DevAddress;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) != RESET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ /* No need to generate STOP, it is automatically done */
+ /* Error callback will be send during stop flag treatment */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* If a pending TXIS flag is set */
+ /* Write a dummy data in TXDR */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ hi2c->Instance->TXDR = 0x00;
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++);
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) != RESET)
+ {
+ if((hi2c->XferSize == 0)&&(hi2c->XferCount!=0))
+ {
+ DevAddress = (hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ if(hi2c->XferCount > 255)
+ {
+ I2C_TransferConfig(hi2c, DevAddress, 255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ if(hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, hi2c->XferOptions, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ }
+ else
+ {
+ /* Call TxCpltCallback() if no stop mode is set */
+ if((I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)&&(hi2c->Mode == HAL_I2C_MODE_MASTER))
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_RX */
+ else
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+ }
+ }
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Wrong size Status regarding TCR flag event */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_SIZE;
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TC) == SET)
+ {
+ if(hi2c->XferCount == 0)
+ {
+ if((I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)&&(hi2c->Mode == HAL_I2C_MODE_MASTER))
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* No Generate Stop, to permit restart mode */
+ /* The stop will be done at the end of transfer, when I2C_AUTOEND_MODE enable */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_RX */
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Wrong size Status regarding TC flag event */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_SIZE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ }
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) != RESET)
+ {
+ if(hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* If a pending TXIS flag is set */
+ /* Write a dummy data in TXDR to clear it */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ hi2c->Instance->TXDR = 0x00;
+ }
+ }
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Flush TX register if not empty */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ if (hi2c->Mode == HAL_I2C_MODE_MEM)
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_MemTxCpltCallback(hi2c);
+ }
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+ }
+ }
+ }
+ else if(hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ if (hi2c->Mode == HAL_I2C_MODE_MEM)
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ HAL_I2C_MemRxCpltCallback(hi2c);
+ }
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+ }
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Slave_ISR(I2C_HandleTypeDef *hi2c)
+{
+ uint8_t TransferDirection = 0;
+ uint16_t SlaveAddrCode = 0;
+ uint16_t OwnAdd1Code = 0;
+ uint16_t OwnAdd2Code = 0;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) != RESET)
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if(hi2c->XferCount == 0)
+ {
+ if(((hi2c->XferOptions == I2C_FIRST_AND_LAST_FRAME) || (hi2c->XferOptions == I2C_LAST_FRAME)) && \
+ (hi2c->State == HAL_I2C_STATE_LISTEN))
+ {
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Store Last receive data if any */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+
+ /* Disable all Interrupts*/
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+ HAL_I2C_ListenCpltCallback(hi2c);
+ }
+ else if((hi2c->XferOptions != I2C_NO_OPTION_FRAME) && (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN))
+ {
+ /* Last Byte is Transmitted */
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_TX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Disable all Interrupts*/
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Check if TXIS flag is SET */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ /* Send a dummy data, to clear TXIS event */
+ hi2c->Instance->TXDR = 0x00;
+
+ /* Flush TX register if not empty */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Tx complete callback to inform upper layer of the end of transmit process */
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ if(hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ /* Set HAL State to "Idle" State, mean to LISTEN state */
+ /* So reset Slave Busy state */
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Disable RX/TX Interrupts, keep only ADDR Interrupt */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+ }
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Error callback to prevent upper layer */
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ if((hi2c->XferCount == 0)&&(hi2c->XferOptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Last Byte is received, disable Interrupt */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_RX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Rx complete callback to inform upper layer of the end of receive process */
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+ }
+
+ if((hi2c->XferCount == 0) && \
+ (hi2c->XferOptions != I2C_NO_OPTION_FRAME) && \
+ (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ /* Last Byte is received, disable Interrupt */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_RX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) != RESET)
+ {
+ /* Disable ADDR interrupt to prevent multiple ADDRInterrupt*/
+ /* Other ADDRInterrupt will be treat in next Listen usecase */
+ if(hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ TransferDirection = I2C_GET_DIR(hi2c);
+ SlaveAddrCode = I2C_GET_ADDR_MATCH(hi2c);
+ OwnAdd1Code = I2C_GET_OWN_ADDRESS1(hi2c);
+ OwnAdd2Code = I2C_GET_OWN_ADDRESS2(hi2c);
+
+ /* If 10bits addressing mode is selected */
+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ if((SlaveAddrCode & SlaveAddr_MSK) == ((OwnAdd1Code >> SlaveAddr_SHIFT) & SlaveAddr_MSK))
+ {
+ SlaveAddrCode = OwnAdd1Code;
+ hi2c->AddrEventCount++;
+ if(hi2c->AddrEventCount == 2)
+ {
+ /* Reset Address Event counter */
+ hi2c->AddrEventCount = 0;
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+ HAL_I2C_AddrCallback(hi2c, TransferDirection, SlaveAddrCode);
+ }
+ }
+ else
+ {
+ SlaveAddrCode = OwnAdd2Code;
+
+ /* Disable ADDR Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+ HAL_I2C_AddrCallback(hi2c, TransferDirection, SlaveAddrCode);
+ }
+ }
+ /* else 7 bits addressing mode is selected */
+ else
+ {
+ /* Disable ADDR Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+ HAL_I2C_AddrCallback(hi2c, TransferDirection, SlaveAddrCode);
+ }
+ }
+ else
+ {
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ /* Write data to TXDR only if XferCount not reach "0" */
+ /* A TXIS flag can be set, during STOP treatment */
+ /* Check if all Datas have already been sent */
+ /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
+ if(hi2c->XferCount > 0)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++);
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+ else
+ {
+ if(((hi2c->XferOptions == I2C_NEXT_FRAME) || (hi2c->XferOptions == I2C_FIRST_FRAME)) && (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN))
+ {
+ /* Last Byte is Transmitted */
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_TX, keep only HAL_I2C_STATE_LISTEN */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Tx complete callback to inform upper layer of the end of transmit process */
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+ }
+ }
+ }
+
+ /* Check if STOPF is set */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) != RESET)
+ {
+ /* Disable all interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT | I2C_XFER_RX_IT);
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Flush TX register if not empty */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+
+ /* Store Last receive data if any */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_ADDR);
+
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ if(hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ hi2c->XferOptions = 0;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Listen Complete callback, to prevent upper layer of the end of Listen usecase */
+ HAL_I2C_ListenCpltCallback(hi2c);
+ }
+ else
+ {
+ if(hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Slave Rx Complete callback */
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+ }
+ else
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Slave Tx Complete callback */
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Master sends target device address followed by internal memory address for write request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
+{
+ I2C_TransferConfig(hi2c,DevAddress,MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* If Memory address size is 8Bit */
+ if(MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Send Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Send MSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Send LSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+return HAL_OK;
+}
+
+/**
+ * @brief Master sends target device address followed by internal memory address for read request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
+{
+ I2C_TransferConfig(hi2c,DevAddress,MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* If Memory address size is 8Bit */
+ if(MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Send Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Send MSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Send LSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ /* Wait until TC flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DMA I2C master transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+ uint16_t DevAddress;
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if last DMA request was done with RELOAD */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, I2C_TIMEOUT_TCR, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ hi2c->pBuffPtr += hi2c->XferSize;
+ hi2c->XferCount -= hi2c->XferSize;
+ if(hi2c->XferCount > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ DevAddress = (hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, I2C_TIMEOUT_TXIS, tickstart) != HAL_OK)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ }
+ else
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+ }
+ }
+}
+
+/**
+ * @brief DMA I2C slave transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Wait until STOP flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Normal Use case, a AF is generated by master */
+ /* to inform slave the end of transfer */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c,I2C_FLAG_STOPF);
+
+ /* Wait until BUSY flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+ }
+}
+
+/**
+ * @brief DMA I2C master receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+ uint16_t DevAddress;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if last DMA request was done with RELOAD */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, I2C_TIMEOUT_TCR, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ hi2c->pBuffPtr += hi2c->XferSize;
+ hi2c->XferCount -= hi2c->XferSize;
+ if(hi2c->XferCount > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ DevAddress = (hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize);
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, I2C_TIMEOUT_RXNE, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ }
+ }
+ else
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+ }
+ }
+}
+
+/**
+ * @brief DMA I2C slave receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOPF flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Wait until BUSY flag is reset */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+ }
+}
+
+/**
+ * @brief DMA I2C Memory Write process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMemTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+ uint16_t DevAddress;
+ I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if last DMA request was done with RELOAD */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, I2C_TIMEOUT_TCR, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ hi2c->pBuffPtr += hi2c->XferSize;
+ hi2c->XferCount -= hi2c->XferSize;
+ if(hi2c->XferCount > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ DevAddress = (hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, I2C_TIMEOUT_TXIS, tickstart) != HAL_OK)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ }
+ else
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_MemTxCpltCallback(hi2c);
+ }
+ }
+}
+
+/**
+ * @brief DMA I2C Memory Read process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMemReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tickstart = 0;
+ I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ uint16_t DevAddress;
+
+ /* Init tickstart for timeout managment*/
+ tickstart = HAL_GetTick();
+
+ /* Check if last DMA request was done with RELOAD */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ /* Wait until TCR flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, I2C_TIMEOUT_TCR, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ hi2c->pBuffPtr += hi2c->XferSize;
+ hi2c->XferCount -= hi2c->XferSize;
+ if(hi2c->XferCount > 255)
+ {
+ hi2c->XferSize = 255;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ DevAddress = (hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize);
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if size > 255 */
+ if( (hi2c->XferSize == 255) && (hi2c->XferSize < hi2c->XferCount) )
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Wait until RXNE flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, I2C_TIMEOUT_RXNE, tickstart) != HAL_OK)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ }
+ }
+ else
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF, tickstart) != HAL_OK)
+ {
+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ else
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Check if Errors has been detected during transfer */
+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_MemRxCpltCallback(hi2c);
+ }
+ }
+}
+
+/**
+ * @brief DMA I2C communication error callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAError(DMA_HandleTypeDef *hdma)
+{
+ I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Disable Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->XferCount = 0;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ HAL_I2C_ErrorCallback(hi2c);
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Flag Specifies the I2C flag to check.
+ * @param Status The new Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
+{
+ /* Wait until flag is set */
+ if(Status == RESET)
+ {
+ while(__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - Tickstart ) > Timeout))
+ {
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_I2C_GET_FLAG(hi2c, Flag) != RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - Tickstart ) > Timeout))
+ {
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of TXIS flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if(I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of STOP flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if(I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if((Timeout == 0)||((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if(I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check if a STOPF is detected */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if((Timeout == 0)||((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State= HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles Acknowledge failed detection during an I2C Communication.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Wait until STOP Flag is reset */
+ /* AutoEnd should be initiate after AF */
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear NACKF Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Flush TX register if not empty */
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_AF;
+ hi2c->State= HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
+ * @param hi2c I2C handle.
+ * @param DevAddress Specifies the slave address to be programmed.
+ * @param Size Specifies the number of bytes to be programmed.
+ * This parameter must be a value between 0 and 255.
+ * @param Mode New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_RELOAD_MODE Enable Reload mode .
+ * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
+ * @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
+ * @param Request New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
+ * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
+ * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
+ * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
+ * @retval None
+ */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_TRANSFER_MODE(Mode));
+ assert_param(IS_TRANSFER_REQUEST(Request));
+
+ /* Get the CR2 register value */
+ tmpreg = hi2c->Instance->CR2;
+
+ /* clear tmpreg specific bits */
+ tmpreg &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
+
+ /* update tmpreg */
+ tmpreg |= (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << 16 ) & I2C_CR2_NBYTES) | \
+ (uint32_t)Mode | (uint32_t)Request);
+
+ /* update CR2 register */
+ hi2c->Instance->CR2 = tmpreg;
+}
+
+/**
+ * @brief Manage the enabling of Interrupts.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest)
+{
+ uint32_t tmpisr = 0;
+
+ if((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Enable ADDR and STOP interrupt */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and RXI interrupt */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI;
+ }
+
+ if((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and TXI interrupt */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI;
+ }
+
+ /* Enable interrupts only at the end */
+ /* to avoid the risk of I2C interrupt handle execution before */
+ /* all interrupts requested done */
+ __HAL_I2C_ENABLE_IT(hi2c, tmpisr);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Manage the disabling of Interrupts.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest)
+{
+ uint32_t tmpisr = 0;
+
+ if((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Disable TC and TXI interrupts */
+ tmpisr |= I2C_IT_TCI | I2C_IT_TXI;
+
+ if((hi2c->State & HAL_I2C_STATE_LISTEN) != HAL_I2C_STATE_LISTEN)
+ {
+ /* Disable NACK and STOP interrupts */
+ tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+ }
+
+ if((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Disable TC and RXI interrupts */
+ tmpisr |= I2C_IT_TCI | I2C_IT_RXI;
+
+ if((hi2c->State & HAL_I2C_STATE_LISTEN) != HAL_I2C_STATE_LISTEN)
+ {
+ /* Disable NACK and STOP interrupts */
+ tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+ }
+
+ if((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Disable ADDR, NACK and STOP interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ /* Disable interrupts only at the end */
+ /* to avoid a breaking situation like at "t" time */
+ /* all disable interrupts request are not done */
+ __HAL_I2C_DISABLE_IT(hi2c, tmpisr);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_i2c_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_i2c_ex.c
new file mode 100644
index 000000000..c3f9156d3
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_i2c_ex.c
@@ -0,0 +1,350 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_i2c_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief I2C Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of I2C Extended peripheral:
+ * + Extended features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### I2C peripheral Extended features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the I2C interface for STM32L4xx
+ devices contains the following additional features
+
+ (+) Possibility to disable or enable Analog Noise Filter
+ (+) Use of a configured Digital Noise Filter
+ (+) Disable or enable wakeup from Stop modes
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure Noise Filter and Wake Up Feature
+ (#) Configure I2C Analog noise filter using the function HAL_I2CEx_ConfigAnalogFilter()
+ (#) Configure I2C Digital noise filter using the function HAL_I2CEx_ConfigDigitalFilter()
+ (#) Configure the enable or disable of I2C Wake Up Mode using the functions :
+ (++) HAL_I2CEx_EnableWakeUp()
+ (++) HAL_I2CEx_DisableWakeUp()
+ (#) Configure the enable or disable of fast mode plus driving capability using the functions :
+ (++) HAL_I2CEx_EnableFastModePlus()
+ (++) HAL_I2CEx_DisbleFastModePlus()
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2CEx I2CEx
+ * @brief I2C Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup I2CEx_Exported_Functions I2C Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group1 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Noise Filters
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure I2C Analog noise filter.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @param AnalogFilter New state of the Analog filter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Reset I2Cx ANOFF bit */
+ hi2c->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
+
+ /* Set analog filter bit*/
+ hi2c->Instance->CR1 |= AnalogFilter;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Configure I2C Digital noise filter.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Get the old register value */
+ tmpreg = hi2c->Instance->CR1;
+
+ /* Reset I2Cx DNF bits [11:8] */
+ tmpreg &= ~(I2C_CR1_DNF);
+
+ /* Set I2Cx DNF coefficient */
+ tmpreg |= DigitalFilter << 8;
+
+ /* Store the new register value */
+ hi2c->Instance->CR1 = tmpreg;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Enable I2C wakeup from stop mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp (I2C_HandleTypeDef *hi2c)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Enable wakeup from stop mode */
+ hi2c->Instance->CR1 |= I2C_CR1_WUPEN;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Disable I2C wakeup from stop mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp (I2C_HandleTypeDef *hi2c)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+
+ if(hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Enable wakeup from stop mode */
+ hi2c->Instance->CR1 &= ~(I2C_CR1_WUPEN);
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Enable the I2C fast mode plus driving capability.
+ * @param ConfigFastModePlus Selects the pin.
+ * This parameter can be one of the @ref I2CEx_FastModePlus values
+ * @note For I2C1, fast mode plus driving capability can be enabled on all selected
+ * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
+ * on each one of the following pins PB6, PB7, PB8 and PB9.
+ * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
+ * can be enabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
+ * @note For all I2C2 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C2 parameter.
+ * @note For all I2C3 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C3 parameter.
+ * @retval None
+ */
+void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus)
+{
+ /* Check the parameter */
+ assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
+
+ /* Enable SYSCFG clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ /* Enable fast mode plus driving capability for selected pin */
+ SET_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus);
+}
+
+/**
+ * @brief Disable the I2C fast mode plus driving capability.
+ * @param ConfigFastModePlus Selects the pin.
+ * This parameter can be one of the @ref I2CEx_FastModePlus values
+ * @note For I2C1, fast mode plus driving capability can be disabled on all selected
+ * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
+ * on each one of the following pins PB6, PB7, PB8 and PB9.
+ * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
+ * can be disabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
+ * @note For all I2C2 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C2 parameter.
+ * @note For all I2C3 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C3 parameter.
+ * @retval None
+ */
+void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus)
+{
+ /* Check the parameter */
+ assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
+
+ /* Enable SYSCFG clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ /* Disable fast mode plus driving capability for selected pin */
+ CLEAR_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_pcd.c b/stmhal/hal/l4/src/stm32l4xx_hal_pcd.c
new file mode 100644
index 000000000..f39dfe38e
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_pcd.c
@@ -0,0 +1,1255 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_pcd.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief PCD HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the USB Peripheral Controller:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The PCD HAL driver can be used as follows:
+
+ (#) Declare a PCD_HandleTypeDef handle structure, for example:
+ PCD_HandleTypeDef hpcd;
+
+ (#) Fill parameters of Init structure in HCD handle
+
+ (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
+
+ (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
+ (##) Enable the PCD/USB Low Level interface clock using
+ (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
+ (##) Initialize the related GPIO clocks
+ (##) Configure PCD pin-out
+ (##) Configure PCD NVIC interrupt
+
+ (#)Associate the Upper USB device stack to the HAL PCD Driver:
+ (##) hpcd.pData = pdev;
+
+ (#)Enable PCD transmission and reception:
+ (##) HAL_PCD_Start();
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+#if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PCD PCD
+ * @brief PCD HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup PCD_Private_Macros PCD Private Macros
+ * @{
+ */
+#define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
+/**
+ * @}
+ */
+
+/* Private functions prototypes ----------------------------------------------*/
+/** @defgroup PCD_Private_Functions PCD Private Functions
+ * @{
+ */
+static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup PCD_Exported_Functions PCD Exported Functions
+ * @{
+ */
+
+/** @defgroup PCD_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:
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the PCD according to the specified
+ * parameters in the PCD_InitTypeDef and initialize the associated handle.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
+{
+ uint32_t i = 0;
+
+ /* Check the PCD handle allocation */
+ if(hpcd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
+
+ if(hpcd->State == HAL_PCD_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hpcd->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_PCD_MspInit(hpcd);
+ }
+
+ hpcd->State = HAL_PCD_STATE_BUSY;
+
+ /* Disable the Interrupts */
+ __HAL_PCD_DISABLE(hpcd);
+
+ /*Init the Core (common init.) */
+ USB_CoreInit(hpcd->Instance, hpcd->Init);
+
+ /* Force Device Mode*/
+ USB_SetCurrentMode(hpcd->Instance , USB_OTG_DEVICE_MODE);
+
+ /* Init endpoints structures */
+ for (i = 0; i < hpcd->Init.dev_endpoints ; i++)
+ {
+ /* Init ep structure */
+ hpcd->IN_ep[i].is_in = 1;
+ hpcd->IN_ep[i].num = i;
+ hpcd->IN_ep[i].tx_fifo_num = i;
+ /* Control until ep is activated */
+ hpcd->IN_ep[i].type = EP_TYPE_CTRL;
+ hpcd->IN_ep[i].maxpacket = 0;
+ hpcd->IN_ep[i].xfer_buff = 0;
+ hpcd->IN_ep[i].xfer_len = 0;
+ }
+
+ for (i = 0; i < hpcd->Init.dev_endpoints ; i++)
+ {
+ hpcd->OUT_ep[i].is_in = 0;
+ hpcd->OUT_ep[i].num = i;
+ hpcd->IN_ep[i].tx_fifo_num = i;
+ /* Control until ep is activated */
+ hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
+ hpcd->OUT_ep[i].maxpacket = 0;
+ hpcd->OUT_ep[i].xfer_buff = 0;
+ hpcd->OUT_ep[i].xfer_len = 0;
+
+ hpcd->Instance->DIEPTXF[i] = 0;
+ }
+
+ /* Init Device */
+ USB_DevInit(hpcd->Instance, hpcd->Init);
+
+ hpcd->State= HAL_PCD_STATE_READY;
+
+ /* Activate LPM */
+ if (hpcd->Init.lpm_enable ==1)
+ {
+ HAL_PCDEx_ActivateLPM(hpcd);
+ }
+ /* Activate Battery charging */
+ if (hpcd->Init.battery_charging_enable ==1)
+ {
+ HAL_PCDEx_ActivateBCD(hpcd);
+ }
+ USB_DevDisconnect (hpcd->Instance);
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the PCD peripheral.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
+{
+ /* Check the PCD handle allocation */
+ if(hpcd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ hpcd->State = HAL_PCD_STATE_BUSY;
+
+ /* Stop Device */
+ HAL_PCD_Stop(hpcd);
+
+ /* DeInit the low level hardware */
+ HAL_PCD_MspDeInit(hpcd);
+
+ hpcd->State = HAL_PCD_STATE_RESET;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the PCD MSP.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes PCD MSP.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the PCD data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start The USB OTG Device.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
+{
+ __HAL_LOCK(hpcd);
+ USB_DevConnect (hpcd->Instance);
+ __HAL_PCD_ENABLE(hpcd);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop The USB OTG Device.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
+{
+ __HAL_LOCK(hpcd);
+ __HAL_PCD_DISABLE(hpcd);
+ USB_StopDevice(hpcd->Instance);
+ USB_DevDisconnect (hpcd->Instance);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles PCD interrupt request.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t i = 0, ep_intr = 0, epint = 0, epnum = 0;
+ uint32_t fifoemptymsk = 0, temp = 0;
+ USB_OTG_EPTypeDef *ep;
+
+ /* ensure that we are in device mode */
+ if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
+ {
+ /* avoid spurious interrupt */
+ if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
+ {
+ return;
+ }
+
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
+ {
+ /* incorrect mode, acknowledge the interrupt */
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
+ }
+
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
+ {
+ epnum = 0;
+
+ /* Read in the device interrupt bits */
+ ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
+
+ while ( ep_intr )
+ {
+ if (ep_intr & 0x1)
+ {
+ epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
+
+ if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
+
+ if ((( (USBx_OUTEP(0)->DOEPINT & 0x8000) == 0)) )
+ {
+
+ if(hpcd->Init.dma_enable == 1)
+ {
+ hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket- (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
+ hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;
+ }
+
+ HAL_PCD_DataOutStageCallback(hpcd, epnum);
+
+ if(hpcd->Init.dma_enable == 1)
+ {
+ if((epnum == 0) && (hpcd->OUT_ep[epnum].xfer_len == 0))
+ {
+ /* this is ZLP, so prepare EP0 for next setup */
+ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
+ }
+ }
+ }
+ /* Clear the SetPktRcvd flag*/
+ USBx_OUTEP(0)->DOEPINT |= 0x8020;
+ }
+
+ if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
+ {
+ /* Inform the upper layer that a setup packet is available */
+ HAL_PCD_SetupStageCallback(hpcd);
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
+ }
+
+ if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
+ }
+ }
+ epnum++;
+ ep_intr >>= 1;
+ }
+ }
+
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
+ {
+ /* Read in the device interrupt bits */
+ ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
+
+ epnum = 0;
+
+ while ( ep_intr )
+ {
+ if (ep_intr & 0x1) /* In ITR */
+ {
+ epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
+
+ if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
+ {
+ fifoemptymsk = 0x1 << epnum;
+ USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
+
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
+
+ if (hpcd->Init.dma_enable == 1)
+ {
+ hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
+ }
+
+ HAL_PCD_DataInStageCallback(hpcd, epnum);
+
+ if (hpcd->Init.dma_enable == 1)
+ {
+ /* this is ZLP, so prepare EP0 for next setup */
+ if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0))
+ {
+ /* prepare to rx more setup packets */
+ USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
+ }
+ }
+ }
+ if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
+ {
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
+ }
+ if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
+ {
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
+ }
+ if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
+ {
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
+ }
+ if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
+ {
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
+ }
+ if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
+ {
+ PCD_WriteEmptyTxFifo(hpcd , epnum);
+ }
+ }
+ epnum++;
+ ep_intr >>= 1;
+ }
+ }
+
+ /* Handle Resume Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
+ {
+ /* Clear the Remote Wake-up Signaling */
+ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
+
+ if(hpcd->LPM_State == LPM_L1)
+ {
+ hpcd->LPM_State = LPM_L0;
+ HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
+ }
+ else
+ {
+ HAL_PCD_ResumeCallback(hpcd);
+ }
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
+ }
+
+ /* Handle Suspend Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
+ {
+ if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
+ {
+
+ HAL_PCD_SuspendCallback(hpcd);
+ }
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
+ }
+
+ /* Handle LPM Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
+ {
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
+ if( hpcd->LPM_State == LPM_L0)
+ {
+ hpcd->LPM_State = LPM_L1;
+ hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ;
+ HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
+ }
+ else
+ {
+ HAL_PCD_SuspendCallback(hpcd);
+ }
+ }
+
+ /* Handle Reset Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
+ {
+ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
+ USB_FlushTxFifo(hpcd->Instance , 0 );
+
+ for (i = 0; i < hpcd->Init.dev_endpoints ; i++)
+ {
+ USBx_INEP(i)->DIEPINT = 0xFF;
+ USBx_OUTEP(i)->DOEPINT = 0xFF;
+ }
+ USBx_DEVICE->DAINT = 0xFFFFFFFF;
+ USBx_DEVICE->DAINTMSK |= 0x10001;
+
+ if(hpcd->Init.use_dedicated_ep1)
+ {
+ USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
+ USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
+ }
+ else
+ {
+ USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
+ USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
+ }
+
+ /* Set Default Address to 0 */
+ USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
+
+ /* setup EP0 to receive SETUP packets */
+ USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
+ }
+
+ /* Handle Enumeration done Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
+ {
+ USB_ActivateSetup(hpcd->Instance);
+ hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
+
+ hpcd->Init.speed = USB_OTG_SPEED_FULL;
+ hpcd->Init.ep0_mps = USB_OTG_FS_MAX_PACKET_SIZE ;
+ hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
+
+ HAL_PCD_ResetCallback(hpcd);
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
+ }
+
+ /* Handle RxQLevel Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
+ {
+ USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+
+ temp = USBx->GRXSTSP;
+
+ ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
+
+ if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
+ {
+ if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
+ {
+ USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
+ ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
+ ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
+ }
+ }
+ else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
+ {
+ USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
+ ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
+ }
+ USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+ }
+
+ /* Handle SOF Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
+ {
+ HAL_PCD_SOFCallback(hpcd);
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
+ }
+
+ /* Handle Incomplete ISO IN Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
+ {
+ HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
+ }
+
+ /* Handle Incomplete ISO OUT Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
+ {
+ HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
+ }
+
+ /* Handle Connection event Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
+ {
+ HAL_PCD_ConnectCallback(hpcd);
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
+ }
+
+ /* Handle Disconnection event Interrupt */
+ if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
+ {
+ temp = hpcd->Instance->GOTGINT;
+
+ if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
+ {
+ HAL_PCD_DisconnectCallback(hpcd);
+ }
+ hpcd->Instance->GOTGINT |= temp;
+ }
+ }
+}
+
+/**
+ * @brief Data OUT stage callback.
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_DataOutStageCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Data IN stage callback.
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_DataInStageCallback could be implemented in the user file
+ */
+}
+/**
+ * @brief Setup stage callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_SetupStageCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief USB Start Of Frame callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_SOFCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief USB Reset callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ResetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Suspend event callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_SuspendCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Resume event callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ResumeCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Incomplete ISO OUT callback.
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Incomplete ISO IN callback.
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Connection event callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ConnectCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Disconnection event callback.
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_DisconnectCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the PCD data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Connect the USB device.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
+{
+ __HAL_LOCK(hpcd);
+ USB_DevConnect(hpcd->Instance);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+
+/**
+ * @brief Disconnect the USB device.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
+{
+ __HAL_LOCK(hpcd);
+ USB_DevDisconnect(hpcd->Instance);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the USB Device address.
+ * @param hpcd: PCD handle
+ * @param address: new device address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
+{
+ __HAL_LOCK(hpcd);
+ USB_SetDevAddress(hpcd->Instance, address);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+/**
+ * @brief Open and configure an endpoint.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @param ep_mps: endpoint max packet size
+ * @param ep_type: endpoint type
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
+{
+ HAL_StatusTypeDef ret = HAL_OK;
+ USB_OTG_EPTypeDef *ep;
+
+ if ((ep_addr & 0x80) == 0x80)
+ {
+ ep = &hpcd->IN_ep[ep_addr & 0x7F];
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr & 0x7F];
+ }
+ ep->num = ep_addr & 0x7F;
+
+ ep->is_in = (0x80 & ep_addr) != 0;
+ ep->maxpacket = ep_mps;
+ ep->type = ep_type;
+ if (ep->is_in)
+ {
+ /* Assign a Tx FIFO */
+ ep->tx_fifo_num = ep->num;
+ }
+ /* Set initial data PID. */
+ if (ep_type == EP_TYPE_BULK )
+ {
+ ep->data_pid_start = 0;
+ }
+
+ __HAL_LOCK(hpcd);
+ USB_ActivateEndpoint(hpcd->Instance , ep);
+ __HAL_UNLOCK(hpcd);
+ return ret;
+}
+
+
+/**
+ * @brief Deactivate an endpoint.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+ USB_OTG_EPTypeDef *ep;
+
+ if ((ep_addr & 0x80) == 0x80)
+ {
+ ep = &hpcd->IN_ep[ep_addr & 0x7F];
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr & 0x7F];
+ }
+ ep->num = ep_addr & 0x7F;
+
+ ep->is_in = (0x80 & ep_addr) != 0;
+
+ __HAL_LOCK(hpcd);
+ USB_DeactivateEndpoint(hpcd->Instance , ep);
+ __HAL_UNLOCK(hpcd);
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Receive an amount of data.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @param pBuf: pointer to the reception buffer
+ * @param len: amount of data to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
+{
+ USB_OTG_EPTypeDef *ep;
+
+ ep = &hpcd->OUT_ep[ep_addr & 0x7F];
+
+ /*setup and start the Xfer */
+ ep->xfer_buff = pBuf;
+ ep->xfer_len = len;
+ ep->xfer_count = 0;
+ ep->is_in = 0;
+ ep->num = ep_addr & 0x7F;
+
+ if (hpcd->Init.dma_enable == 1)
+ {
+ ep->dma_addr = (uint32_t)pBuf;
+ }
+
+ __HAL_LOCK(hpcd);
+
+ if ((ep_addr & 0x7F) == 0 )
+ {
+ USB_EP0StartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
+ }
+ else
+ {
+ USB_EPStartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
+ }
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get Received Data Size.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @retval Data Size
+ */
+uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+ return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
+}
+/**
+ * @brief Send an amount of data.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @param pBuf: pointer to the transmission buffer
+ * @param len: amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
+{
+ USB_OTG_EPTypeDef *ep;
+
+ ep = &hpcd->IN_ep[ep_addr & 0x7F];
+
+ /*setup and start the Xfer */
+ ep->xfer_buff = pBuf;
+ ep->xfer_len = len;
+ ep->xfer_count = 0;
+ ep->is_in = 1;
+ ep->num = ep_addr & 0x7F;
+
+ if (hpcd->Init.dma_enable == 1)
+ {
+ ep->dma_addr = (uint32_t)pBuf;
+ }
+
+ __HAL_LOCK(hpcd);
+
+ if ((ep_addr & 0x7F) == 0 )
+ {
+ USB_EP0StartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
+ }
+ else
+ {
+ USB_EPStartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
+ }
+
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set a STALL condition over an endpoint.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+ USB_OTG_EPTypeDef *ep;
+
+ if ((0x80 & ep_addr) == 0x80)
+ {
+ ep = &hpcd->IN_ep[ep_addr & 0x7F];
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr];
+ }
+
+ ep->is_stall = 1;
+ ep->num = ep_addr & 0x7F;
+ ep->is_in = ((ep_addr & 0x80) == 0x80);
+
+
+ __HAL_LOCK(hpcd);
+ USB_EPSetStall(hpcd->Instance , ep);
+ if((ep_addr & 0x7F) == 0)
+ {
+ USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
+ }
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Clear a STALL condition over in an endpoint.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+ USB_OTG_EPTypeDef *ep;
+
+ if ((0x80 & ep_addr) == 0x80)
+ {
+ ep = &hpcd->IN_ep[ep_addr & 0x7F];
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr];
+ }
+
+ ep->is_stall = 0;
+ ep->num = ep_addr & 0x7F;
+ ep->is_in = ((ep_addr & 0x80) == 0x80);
+
+ __HAL_LOCK(hpcd);
+ USB_EPClearStall(hpcd->Instance , ep);
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Flush an endpoint.
+ * @param hpcd: PCD handle
+ * @param ep_addr: endpoint address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+ __HAL_LOCK(hpcd);
+
+ if ((ep_addr & 0x80) == 0x80)
+ {
+ USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
+ }
+ else
+ {
+ USB_FlushRxFifo(hpcd->Instance);
+ }
+
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Activate remote wakeup signalling.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
+ {
+ /* Activate Remote wakeup signaling */
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief De-activate remote wakeup signalling.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ /* De-activate Remote wakeup signaling */
+ USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
+ * @brief 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 PCD handle state.
+ * @param hpcd: PCD handle
+ * @retval HAL state
+ */
+PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
+{
+ return hpcd->State;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup PCD_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Check FIFO for the next packet to be loaded.
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ USB_OTG_EPTypeDef *ep;
+ int32_t len = 0;
+ uint32_t len32b;
+ uint32_t fifoemptymsk = 0;
+
+ ep = &hpcd->IN_ep[epnum];
+ len = ep->xfer_len - ep->xfer_count;
+
+ if (len > ep->maxpacket)
+ {
+ len = ep->maxpacket;
+ }
+
+
+ len32b = (len + 3) / 4;
+
+ while ( (USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
+ ep->xfer_count < ep->xfer_len &&
+ ep->xfer_len != 0)
+ {
+ /* Write the FIFO */
+ len = ep->xfer_len - ep->xfer_count;
+
+ if (len > ep->maxpacket)
+ {
+ len = ep->maxpacket;
+ }
+ len32b = (len + 3) / 4;
+
+ USB_WritePacket(USBx, ep->xfer_buff, epnum, len, hpcd->Init.dma_enable);
+
+ ep->xfer_buff += len;
+ ep->xfer_count += len;
+ }
+
+ if(len <= 0)
+ {
+ fifoemptymsk = 0x1 << epnum;
+ USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
+
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PCD_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_pcd_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_pcd_ex.c
new file mode 100644
index 000000000..29a85da6a
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_pcd_ex.c
@@ -0,0 +1,323 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_pcd_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief PCD Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the USB Peripheral Controller:
+ * + Extended features functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+#if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PCDEx PCDEx
+ * @brief PCD Extended HAL module driver
+ * @{
+ */
+#ifdef HAL_PCD_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
+ * @{
+ */
+
+/** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
+ * @brief PCDEx control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Update FIFO configuration
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set Tx FIFO
+ * @param hpcd: PCD handle
+ * @param fifo: The number of Tx fifo
+ * @param size: Fifo size
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size)
+{
+ uint8_t i = 0;
+ uint32_t Tx_Offset = 0;
+
+ /* TXn min size = 16 words. (n : Transmit FIFO index)
+ When a TxFIFO is not used, the Configuration should be as follows:
+ case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
+ --> Txm can use the space allocated for Txn.
+ case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
+ --> Txn should be configured with the minimum space of 16 words
+ The FIFO is used optimally when used TxFIFOs are allocated in the top
+ of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
+ When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
+
+ Tx_Offset = hpcd->Instance->GRXFSIZ;
+
+ if(fifo == 0)
+ {
+ hpcd->Instance->DIEPTXF0_HNPTXFSIZ = (size << 16) | Tx_Offset;
+ }
+ else
+ {
+ Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
+ for (i = 0; i < (fifo - 1); i++)
+ {
+ Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
+ }
+
+ /* Multiply Tx_Size by 2 to get higher performance */
+ hpcd->Instance->DIEPTXF[fifo - 1] = (size << 16) | Tx_Offset;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Rx FIFO
+ * @param hpcd: PCD handle
+ * @param size: Size of Rx fifo
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
+{
+ hpcd->Instance->GRXFSIZ = size;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Activate LPM feature.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ hpcd->lpm_active = ENABLE;
+ hpcd->LPM_State = LPM_L0;
+ USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM;
+ USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate LPM feature.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ hpcd->lpm_active = DISABLE;
+ USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM;
+ USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle BatteryCharging Process.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Start BCD When device is connected */
+ if (USBx_DEVICE->DCTL & USB_OTG_DCTL_SDIS)
+ {
+ /* Enable DCD : Data Contact Detect */
+ USBx->GCCFG |= USB_OTG_GCCFG_DCDEN;
+
+ /* Wait Detect flag or a timeout is happen*/
+ while ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == 0)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart ) > 1000)
+ {
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
+ return;
+ }
+ }
+
+ /* Right response got */
+ HAL_Delay(100);
+
+ /* Check Detect flag*/
+ if (USBx->GCCFG & USB_OTG_GCCFG_DCDET)
+ {
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
+ }
+
+ /*Primary detection: checks if connected to Standard Downstream Port
+ (without charging capability) */
+ USBx->GCCFG &=~ USB_OTG_GCCFG_DCDEN;
+ USBx->GCCFG |= USB_OTG_GCCFG_PDEN;
+ HAL_Delay(100);
+
+ if (!(USBx->GCCFG & USB_OTG_GCCFG_PDET))
+ {
+ /* Case of Standard Downstream Port */
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
+ }
+ else
+ {
+ /* start secondary detection to check connection to Charging Downstream
+ Port or Dedicated Charging Port */
+ USBx->GCCFG &=~ USB_OTG_GCCFG_PDEN;
+ USBx->GCCFG |= USB_OTG_GCCFG_SDEN;
+ HAL_Delay(100);
+
+ if ((USBx->GCCFG) & USB_OTG_GCCFG_SDET)
+ {
+ /* case Dedicated Charging Port */
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
+ }
+ else
+ {
+ /* case Charging Downstream Port */
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
+ }
+ }
+ /* Battery Charging capability discovery finished */
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
+ }
+}
+
+/**
+ * @brief Activate BatteryCharging feature.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ hpcd->battery_charging_active = ENABLE;
+ USBx->GCCFG |= (USB_OTG_GCCFG_BCDEN);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate BatteryCharging feature.
+ * @param hpcd: PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ hpcd->battery_charging_active = DISABLE;
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
+ return HAL_OK;
+}
+
+/**
+ * @brief Send LPM message to user layer callback.
+ * @param hpcd: PCD handle
+ * @param msg: LPM message
+ * @retval HAL status
+ */
+__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(msg);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCDEx_LPM_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Send BatteryCharging message to user layer callback.
+ * @param hpcd: PCD handle
+ * @param msg: LPM message
+ * @retval HAL status
+ */
+__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(msg);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCDEx_BCD_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PCD_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_pwr.c b/stmhal/hal/l4/src/stm32l4xx_hal_pwr.c
new file mode 100644
index 000000000..68e6fe7dd
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_pwr.c
@@ -0,0 +1,676 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_pwr.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @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
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PWR PWR
+ * @brief PWR HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup PWR_Private_Defines PWR Private Defines
+ * @{
+ */
+
+/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask
+ * @{
+ */
+#define PVD_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVD threshold crossing */
+#define PVD_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVD threshold crossing */
+#define PVD_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVD trigger */
+#define PVD_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVD trigger */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup PWR_Exported_Functions PWR Exported Functions
+ * @{
+ */
+
+/** @defgroup 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)
+{
+ __HAL_RCC_PWR_FORCE_RESET();
+ __HAL_RCC_PWR_RELEASE_RESET();
+}
+
+/**
+ * @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);
+}
+
+
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup 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 SRAM2: all clocks are stopped except LSI and LSE, SRAM2 content preserved, main regulator off, low power regulator on.
+ (+) Standby mode without SRAM2: 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 or HAL_PWREx_EnterSTOP1Mode() for mode 1 or for porting reasons HAL_PWR_EnterSTOPMode().
+ (++) HAL_PWREx_EnterSTOP2Mode() for mode 2.
+ (+) Regulator setting (applicable to HAL_PWR_EnterSTOPMode() only):
+ (++) PWR_MAINREGULATOR_ON
+ (++) PWR_LOWPOWERREGULATOR_ON
+ (+) 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_EnableSRAM2ContentRetention() 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.
+ * @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 */
+ __HAL_PWR_PVD_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVD_EXTI_DISABLE_IT();
+ __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_EVENT();
+ }
+
+ /* 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 Enable the Power Voltage Detector (PVD).
+ * @retval None
+ */
+void HAL_PWR_EnablePVD(void)
+{
+ SET_BIT(PWR->CR2, PWR_CR2_PVDE);
+}
+
+/**
+ * @brief Disable the Power Voltage Detector (PVD).
+ * @retval None
+ */
+void HAL_PWR_DisablePVD(void)
+{
+ 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 @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5
+ * @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 monde 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))
+ {
+ HAL_PWREx_DisableLowPowerRunMode();
+ }
+ /* 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.
+ * @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 or Stop 1 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 SRAM2 content is preserved
+ * in which case the regulator is in low-power mode.
+ * 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_EnableSRAM2ContentRetention() 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.
+ * @retval None
+ */
+void HAL_PWR_EnterSTANDBYMode(void)
+{
+ /* Set Stand-by mode */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_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();
+}
+
+
+
+/**
+ * @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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_pwr_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_pwr_ex.c
new file mode 100644
index 000000000..c4e9e5338
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_pwr_ex.c
@@ -0,0 +1,1176 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_pwr_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief Extended PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Power Controller (PWR) peripheral:
+ * + Extended Initialization and de-initialization functions
+ * + Extended Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PWREx PWREx
+ * @brief PWR Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+#define PWR_PORTH_AVAILABLE_PINS (PWR_GPIO_BIT_0|PWR_GPIO_BIT_1)
+
+/** @defgroup PWR_Extended_Private_Defines PWR Extended Private Defines
+ * @{
+ */
+
+/** @defgroup PWREx_PVM_Mode_Mask PWR PVM Mode Mask
+ * @{
+ */
+#define PVM_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVM threshold crossing */
+#define PVM_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVM threshold crossing */
+#define PVM_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVM trigger */
+#define PVM_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVM trigger */
+/**
+ * @}
+ */
+
+/** @defgroup PWREx_TimeOut_Value PWR Extended Flag Setting Time Out Value
+ * @{
+ */
+#define PWR_FLAG_SETTING_DELAY_US 50 /*!< Time out value for REGLPF and VOSF flags setting */
+/**
+ * @}
+ */
+
+
+
+/**
+ * @}
+ */
+
+
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup PWREx_Exported_Functions PWR Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Return Voltage Scaling Range.
+ * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_RANGE1 or PWR_REGULATOR_VOLTAGE_RANGE2)
+ */
+uint32_t HAL_PWREx_GetVoltageRange(void)
+{
+ return (PWR->CR1 & PWR_CR1_VOS);
+}
+
+
+
+/**
+ * @brief Configure the main internal regulator output voltage.
+ * @param VoltageScaling: specifies the regulator output voltage to achieve
+ * a tradeoff between performance and power consumption.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode,
+ * typical output voltage at 1.2 V,
+ * system frequency up to 80 MHz.
+ * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode,
+ * typical output voltage at 1.0 V,
+ * system frequency up to 26 MHz.
+ * @note When moving from Range 1 to Range 2, the system frequency must be decreased to
+ * a value below 26 MHz before calling HAL_PWREx_ControlVoltageScaling() API.
+ * When moving from Range 2 to Range 1, the system frequency can be increased to
+ * a value up to 80 MHz after calling HAL_PWREx_ControlVoltageScaling() API.
+ * @note When moving from Range 2 to Range 1, the API waits for VOSF flag to be
+ * cleared before returning the status. If the flag is not cleared within
+ * 50 microseconds, HAL_TIMEOUT status is reported.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling)
+{
+ uint32_t wait_loop_index = 0;
+
+ assert_param(IS_PWR_VOLTAGE_SCALING_RANGE(VoltageScaling));
+
+ /* If Set Range 1 */
+ if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ /* Set Range 1 */
+ MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /* Wait until VOSF is cleared */
+ wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000));
+ while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)))
+ {
+ wait_loop_index--;
+ }
+ if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE2)
+ {
+ /* Set Range 2 */
+ MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2);
+ /* No need to wait for VOSF to be cleared for this transition */
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Enable battery charging.
+ * When VDD is present, charge the external battery on VBAT thru an internal resistor.
+ * @param ResistorSelection: specifies the resistor impedance.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_5 5 kOhms resistor
+ * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_1_5 1.5 kOhms resistor
+ * @retval None
+ */
+void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection)
+{
+ assert_param(IS_PWR_BATTERY_RESISTOR_SELECT(ResistorSelection));
+
+ /* Specify resistor selection */
+ MODIFY_REG(PWR->CR4, PWR_CR4_VBRS, ResistorSelection);
+
+ /* Enable battery charging */
+ SET_BIT(PWR->CR4, PWR_CR4_VBE);
+}
+
+
+/**
+ * @brief Disable battery charging.
+ * @retval None
+ */
+void HAL_PWREx_DisableBatteryCharging(void)
+{
+ CLEAR_BIT(PWR->CR4, PWR_CR4_VBE);
+}
+
+
+#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
+/**
+ * @brief Enable VDDUSB supply.
+ * @note Remove VDDUSB electrical and logical isolation, once VDDUSB supply is present.
+ * @retval None
+ */
+void HAL_PWREx_EnableVddUSB(void)
+{
+ SET_BIT(PWR->CR2, PWR_CR2_USV);
+}
+
+
+/**
+ * @brief Disable VDDUSB supply.
+ * @retval None
+ */
+void HAL_PWREx_DisableVddUSB(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_CR2_USV);
+}
+#endif /* defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) */
+
+/**
+ * @brief Enable VDDIO2 supply.
+ * @note Remove VDDIO2 electrical and logical isolation, once VDDIO2 supply is present.
+ * @retval None
+ */
+void HAL_PWREx_EnableVddIO2(void)
+{
+ SET_BIT(PWR->CR2, PWR_CR2_IOSV);
+}
+
+
+/**
+ * @brief Disable VDDIO2 supply.
+ * @retval None
+ */
+void HAL_PWREx_DisableVddIO2(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_CR2_IOSV);
+}
+
+
+/**
+ * @brief Enable Internal Wake-up Line.
+ * @retval None
+ */
+void HAL_PWREx_EnableInternalWakeUpLine(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_EIWF);
+}
+
+
+/**
+ * @brief Disable Internal Wake-up Line.
+ * @retval None
+ */
+void HAL_PWREx_DisableInternalWakeUpLine(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_EIWF);
+}
+
+
+
+/**
+ * @brief Enable GPIO pull-up state in Standby and Shutdown modes.
+ * @note Set the relevant PUy bits of PWR_PUCRx register to configure the I/O in
+ * pull-up state in Standby and Shutdown modes.
+ * @note This state is effective in Standby and Shutdown modes only if APC bit
+ * is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
+ * @note The configuration is lost when exiting the Shutdown mode due to the
+ * power-on reset, maintained when exiting the Standby mode.
+ * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding
+ * PDy bit of PWR_PDCRx register is cleared unless it is reserved.
+ * @note Even if a PUy bit to set is reserved, the other PUy bits entered as input
+ * parameter at the same time are set.
+ * @param GPIO: Specify the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber: Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to set
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber)
+{
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ SET_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14))));
+ CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15))));
+ break;
+ case PWR_GPIO_B:
+ SET_BIT(PWR->PUCRB, GPIONumber);
+ CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4))));
+ break;
+ case PWR_GPIO_C:
+ SET_BIT(PWR->PUCRC, GPIONumber);
+ CLEAR_BIT(PWR->PDCRC, GPIONumber);
+ break;
+ case PWR_GPIO_D:
+ SET_BIT(PWR->PUCRD, GPIONumber);
+ CLEAR_BIT(PWR->PDCRD, GPIONumber);
+ break;
+ case PWR_GPIO_E:
+ SET_BIT(PWR->PUCRE, GPIONumber);
+ CLEAR_BIT(PWR->PDCRE, GPIONumber);
+ break;
+ case PWR_GPIO_F:
+ SET_BIT(PWR->PUCRF, GPIONumber);
+ CLEAR_BIT(PWR->PDCRF, GPIONumber);
+ break;
+ case PWR_GPIO_G:
+ SET_BIT(PWR->PUCRG, GPIONumber);
+ CLEAR_BIT(PWR->PDCRG, GPIONumber);
+ break;
+ case PWR_GPIO_H:
+ SET_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Disable GPIO pull-up state in Standby mode and Shutdown modes.
+ * @note Reset the relevant PUy bits of PWR_PUCRx register used to configure the I/O
+ * in pull-up state in Standby and Shutdown modes.
+ * @note Even if a PUy bit to reset is reserved, the other PUy bits entered as input
+ * parameter at the same time are reset.
+ * @param GPIO: Specifies the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber: Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to reset
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber)
+{
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14))));
+ break;
+ case PWR_GPIO_B:
+ CLEAR_BIT(PWR->PUCRB, GPIONumber);
+ break;
+ case PWR_GPIO_C:
+ CLEAR_BIT(PWR->PUCRC, GPIONumber);
+ break;
+ case PWR_GPIO_D:
+ CLEAR_BIT(PWR->PUCRD, GPIONumber);
+ break;
+ case PWR_GPIO_E:
+ CLEAR_BIT(PWR->PUCRE, GPIONumber);
+ break;
+ case PWR_GPIO_F:
+ CLEAR_BIT(PWR->PUCRF, GPIONumber);
+ break;
+ case PWR_GPIO_G:
+ CLEAR_BIT(PWR->PUCRG, GPIONumber);
+ break;
+ case PWR_GPIO_H:
+ CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+
+
+/**
+ * @brief Enable GPIO pull-down state in Standby and Shutdown modes.
+ * @note Set the relevant PDy bits of PWR_PDCRx register to configure the I/O in
+ * pull-down state in Standby and Shutdown modes.
+ * @note This state is effective in Standby and Shutdown modes only if APC bit
+ * is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
+ * @note The configuration is lost when exiting the Shutdown mode due to the
+ * power-on reset, maintained when exiting the Standby mode.
+ * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding
+ * PUy bit of PWR_PUCRx register is cleared unless it is reserved.
+ * @note Even if a PDy bit to set is reserved, the other PDy bits entered as input
+ * parameter at the same time are set.
+ * @param GPIO: Specify the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber: Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to set
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber)
+{
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ SET_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15))));
+ CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14))));
+ break;
+ case PWR_GPIO_B:
+ SET_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4))));
+ CLEAR_BIT(PWR->PUCRB, GPIONumber);
+ break;
+ case PWR_GPIO_C:
+ SET_BIT(PWR->PDCRC, GPIONumber);
+ CLEAR_BIT(PWR->PUCRC, GPIONumber);
+ break;
+ case PWR_GPIO_D:
+ SET_BIT(PWR->PDCRD, GPIONumber);
+ CLEAR_BIT(PWR->PUCRD, GPIONumber);
+ break;
+ case PWR_GPIO_E:
+ SET_BIT(PWR->PDCRE, GPIONumber);
+ CLEAR_BIT(PWR->PUCRE, GPIONumber);
+ break;
+ case PWR_GPIO_F:
+ SET_BIT(PWR->PDCRF, GPIONumber);
+ CLEAR_BIT(PWR->PUCRF, GPIONumber);
+ break;
+ case PWR_GPIO_G:
+ SET_BIT(PWR->PDCRG, GPIONumber);
+ CLEAR_BIT(PWR->PUCRG, GPIONumber);
+ break;
+ case PWR_GPIO_H:
+ SET_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Disable GPIO pull-down state in Standby and Shutdown modes.
+ * @note Reset the relevant PDy bits of PWR_PDCRx register used to configure the I/O
+ * in pull-down state in Standby and Shutdown modes.
+ * @note Even if a PDy bit to reset is reserved, the other PDy bits entered as input
+ * parameter at the same time are reset.
+ * @param GPIO: Specifies the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H
+ * to select the GPIO peripheral.
+ * @param GPIONumber: Specify the I/O pins numbers.
+ * This parameter can be one of the following values:
+ * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for PORTH where less
+ * I/O pins are available) or the logical OR of several of them to reset
+ * several bits for a given port in a single API call.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber)
+{
+ assert_param(IS_PWR_GPIO(GPIO));
+ assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
+
+ switch (GPIO)
+ {
+ case PWR_GPIO_A:
+ CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15))));
+ break;
+ case PWR_GPIO_B:
+ CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4))));
+ break;
+ case PWR_GPIO_C:
+ CLEAR_BIT(PWR->PDCRC, GPIONumber);
+ break;
+ case PWR_GPIO_D:
+ CLEAR_BIT(PWR->PDCRD, GPIONumber);
+ break;
+ case PWR_GPIO_E:
+ CLEAR_BIT(PWR->PDCRE, GPIONumber);
+ break;
+ case PWR_GPIO_F:
+ CLEAR_BIT(PWR->PDCRF, GPIONumber);
+ break;
+ case PWR_GPIO_G:
+ CLEAR_BIT(PWR->PDCRG, GPIONumber);
+ break;
+ case PWR_GPIO_H:
+ CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
+ break;
+ default:
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+
+
+/**
+ * @brief Enable pull-up and pull-down configuration.
+ * @note When APC bit is set, the I/O pull-up and pull-down configurations defined in
+ * PWR_PUCRx and PWR_PDCRx registers are applied in Standby and Shutdown modes.
+ * @note Pull-up set by PUy bit of PWR_PUCRx register is not activated if the corresponding
+ * PDy bit of PWR_PDCRx register is also set (pull-down configuration priority is higher).
+ * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() API's ensure there
+ * is no conflict when setting PUy or PDy bit.
+ * @retval None
+ */
+void HAL_PWREx_EnablePullUpPullDownConfig(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_APC);
+}
+
+
+/**
+ * @brief Disable pull-up and pull-down configuration.
+ * @note When APC bit is cleared, the I/O pull-up and pull-down configurations defined in
+ * PWR_PUCRx and PWR_PDCRx registers are not applied in Standby and Shutdown modes.
+ * @retval None
+ */
+void HAL_PWREx_DisablePullUpPullDownConfig(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_APC);
+}
+
+
+
+/**
+ * @brief Enable SRAM2 content retention in Standby mode.
+ * @note When RRS bit is set, SRAM2 is powered by the low-power regulator in
+ * Standby mode and its content is kept.
+ * @retval None
+ */
+void HAL_PWREx_EnableSRAM2ContentRetention(void)
+{
+ SET_BIT(PWR->CR3, PWR_CR3_RRS);
+}
+
+
+/**
+ * @brief Disable SRAM2 content retention in Standby mode.
+ * @note When RRS bit is reset, SRAM2 is powered off in Standby mode
+ * and its content is lost.
+ * @retval None
+ */
+void HAL_PWREx_DisableSRAM2ContentRetention(void)
+{
+ CLEAR_BIT(PWR->CR3, PWR_CR3_RRS);
+}
+
+
+
+
+#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
+/**
+ * @brief Enable the Power Voltage Monitoring 1: VDDUSB versus 1.2V.
+ * @retval None
+ */
+void HAL_PWREx_EnablePVM1(void)
+{
+ SET_BIT(PWR->CR2, PWR_PVM_1);
+}
+
+/**
+ * @brief Disable the Power Voltage Monitoring 1: VDDUSB versus 1.2V.
+ * @retval None
+ */
+void HAL_PWREx_DisablePVM1(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_PVM_1);
+}
+#endif /* defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) */
+
+
+/**
+ * @brief Enable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V.
+ * @retval None
+ */
+void HAL_PWREx_EnablePVM2(void)
+{
+ SET_BIT(PWR->CR2, PWR_PVM_2);
+}
+
+/**
+ * @brief Disable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V.
+ * @retval None
+ */
+void HAL_PWREx_DisablePVM2(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_PVM_2);
+}
+
+
+/**
+ * @brief Enable the Power Voltage Monitoring 3: VDDA versus 1.62V.
+ * @retval None
+ */
+void HAL_PWREx_EnablePVM3(void)
+{
+ SET_BIT(PWR->CR2, PWR_PVM_3);
+}
+
+/**
+ * @brief Disable the Power Voltage Monitoring 3: VDDA versus 1.62V.
+ * @retval None
+ */
+void HAL_PWREx_DisablePVM3(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_PVM_3);
+}
+
+
+/**
+ * @brief Enable the Power Voltage Monitoring 4: VDDA versus 2.2V.
+ * @retval None
+ */
+void HAL_PWREx_EnablePVM4(void)
+{
+ SET_BIT(PWR->CR2, PWR_PVM_4);
+}
+
+/**
+ * @brief Disable the Power Voltage Monitoring 4: VDDA versus 2.2V.
+ * @retval None
+ */
+void HAL_PWREx_DisablePVM4(void)
+{
+ CLEAR_BIT(PWR->CR2, PWR_PVM_4);
+}
+
+
+
+
+/**
+ * @brief Configure the Peripheral Voltage Monitoring (PVM).
+ * @param sConfigPVM: pointer to a PWR_PVMTypeDef structure that contains the
+ * PVM configuration information.
+ * @note The API configures a single PVM according to the information contained
+ * in the input structure. To configure several PVMs, the API must be singly
+ * called for each PVM used.
+ * @note Refer to the electrical characteristics of your device datasheet for
+ * more details about the voltage thresholds corresponding to each
+ * detection level and to each monitored supply.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_PVM_TYPE(sConfigPVM->PVMType));
+ assert_param(IS_PWR_PVM_MODE(sConfigPVM->Mode));
+
+
+ /* Configure EXTI 35 to 38 interrupts if so required:
+ scan thru PVMType to detect which PVMx is set and
+ configure the corresponding EXTI line accordingly. */
+ switch (sConfigPVM->PVMType)
+ {
+#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
+ case PWR_PVM_1:
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+ __HAL_PWR_PVM1_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVM1_EXTI_DISABLE_IT();
+ __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_EVENT();
+ }
+
+ /* Configure the edge */
+ if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
+ {
+ __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE();
+ }
+ break;
+#endif /* defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) */
+
+ case PWR_PVM_2:
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+ __HAL_PWR_PVM2_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVM2_EXTI_DISABLE_IT();
+ __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
+ {
+ __HAL_PWR_PVM2_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
+ {
+ __HAL_PWR_PVM2_EXTI_ENABLE_EVENT();
+ }
+
+ /* Configure the edge */
+ if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
+ {
+ __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
+ {
+ __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE();
+ }
+ break;
+
+ case PWR_PVM_3:
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+ __HAL_PWR_PVM3_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVM3_EXTI_DISABLE_IT();
+ __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_EVENT();
+ }
+
+ /* Configure the edge */
+ if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
+ {
+ __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE();
+ }
+ break;
+
+ case PWR_PVM_4:
+ /* Clear any previous config. Keep it clear if no event or IT mode is selected */
+ __HAL_PWR_PVM4_EXTI_DISABLE_EVENT();
+ __HAL_PWR_PVM4_EXTI_DISABLE_IT();
+ __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE();
+ __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE();
+
+ /* Configure interrupt mode */
+ if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
+ {
+ __HAL_PWR_PVM4_EXTI_ENABLE_IT();
+ }
+
+ /* Configure event mode */
+ if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
+ {
+ __HAL_PWR_PVM4_EXTI_ENABLE_EVENT();
+ }
+
+ /* Configure the edge */
+ if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
+ {
+ __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE();
+ }
+
+ if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
+ {
+ __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE();
+ }
+ break;
+
+ default:
+ return HAL_ERROR;
+
+ }
+
+
+ return HAL_OK;
+}
+
+
+
+/**
+ * @brief Enter Low-power Run mode
+ * @note In Low-power Run mode, all I/O pins keep the same state as in Run mode.
+ * @note When Regulator is set to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the
+ * Flash in power-down monde in setting the RUN_PD bit in FLASH_ACR register.
+ * Additionally, the clock frequency must be reduced below 2 MHz.
+ * Setting RUN_PD in FLASH_ACR then appropriately reducing the clock frequency must
+ * be done before calling HAL_PWREx_EnableLowPowerRunMode() API.
+ * @retval None
+ */
+void HAL_PWREx_EnableLowPowerRunMode(void)
+{
+ /* Set Regulator parameter */
+ SET_BIT(PWR->CR1, PWR_CR1_LPR);
+}
+
+
+/**
+ * @brief Exit Low-power Run mode.
+ * @note Before HAL_PWREx_DisableLowPowerRunMode() completion, the function checks that
+ * REGLPF has been properly reset (otherwise, HAL_PWREx_DisableLowPowerRunMode
+ * returns HAL_TIMEOUT status). The system clock frequency can then be
+ * increased above 2 MHz.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void)
+{
+ uint32_t wait_loop_index = 0;
+
+ /* Clear LPR bit */
+ CLEAR_BIT(PWR->CR1, PWR_CR1_LPR);
+
+ /* Wait until REGLPF is reset */
+ wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000));
+ while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)))
+ {
+ wait_loop_index--;
+ }
+ if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))
+ {
+ return HAL_TIMEOUT;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Enter Stop 0 mode.
+ * @note In Stop 0 mode, main and low voltage regulators are ON.
+ * @note In Stop 0 mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
+ * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
+ * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
+ * only to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * @note When exiting Stop 0 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @note By keeping the internal regulator ON during Stop 0 mode, the consumption
+ * is higher although the startup time is reduced.
+ * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Stop 0 mode with Main Regulator */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP0);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select Stop mode entry --------------------------------------------------*/
+ if(STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+
+/**
+ * @brief Enter Stop 1 mode.
+ * @note In Stop 1 mode, only low power voltage regulator is ON.
+ * @note In Stop 1 mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
+ * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
+ * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
+ * only to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * @note When exiting Stop 1 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @note Due to low power mode, an additional startup delay is incurred when waking up from Stop 1 mode.
+ * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Stop 1 mode with Low-Power Regulator */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP1);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select Stop mode entry --------------------------------------------------*/
+ if(STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+
+/**
+ * @brief Enter Stop 2 mode.
+ * @note In Stop 2 mode, only low power voltage regulator is ON.
+ * @note In Stop 2 mode, all I/O pins keep the same state as in Run mode.
+ * @note All clocks in the VCORE domain are stopped, the PLL, the MSI,
+ * the HSI and the HSE oscillators are disabled. Some peripherals with wakeup capability
+ * (LCD, LPTIM1, I2C3 and LPUART) can switch on the HSI to receive a frame, and switch off the HSI after
+ * receiving the frame if it is not a wakeup frame. In this case the HSI clock is propagated only
+ * to the peripheral requesting it.
+ * SRAM1, SRAM2 and register contents are preserved.
+ * The BOR is available.
+ * The voltage regulator is set in low-power mode but LPR bit must be cleared to enter stop 2 mode.
+ * Otherwise, Stop 1 mode is entered.
+ * @note When exiting Stop 2 mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
+ * is set; the MSI oscillator is selected if STOPWUCK is cleared.
+ * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
+ * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry)
+{
+ /* Check the parameter */
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Set Stop mode 2 */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP2);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+ /* Select Stop mode entry --------------------------------------------------*/
+ if(STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __SEV();
+ __WFE();
+ __WFE();
+ }
+
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+}
+
+
+
+
+
+/**
+ * @brief Enter Shutdown mode.
+ * @note In Shutdown mode, the PLL, the HSI, the MSI, the LSI and the HSE oscillators are switched
+ * off. The voltage regulator is disabled and Vcore domain is powered off.
+ * SRAM1, SRAM2 and registers contents are lost except for registers in the Backup domain.
+ * The BOR is not available.
+ * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state.
+ * @retval None
+ */
+void HAL_PWREx_EnterSHUTDOWNMode(void)
+{
+
+ /* Set Shutdown mode */
+ MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_SHUTDOWN);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
+
+/* This option is used to ensure that store operations are completed */
+#if defined ( __CC_ARM)
+ __force_stores();
+#endif
+ /* Request Wait For Interrupt */
+ __WFI();
+}
+
+
+
+
+/**
+ * @brief This function handles the PWR PVD/PVMx interrupt request.
+ * @note This API should be called under the PVD_PVM_IRQHandler().
+ * @retval None
+ */
+void HAL_PWREx_PVD_PVM_IRQHandler(void)
+{
+ /* Check PWR exti flag */
+ if(__HAL_PWR_PVD_EXTI_GET_FLAG() != RESET)
+ {
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback();
+
+ /* Clear PVD exti pending bit */
+ __HAL_PWR_PVD_EXTI_CLEAR_FLAG();
+ }
+ /* Next, successively check PVMx exti flags */
+#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
+ if(__HAL_PWR_PVM1_EXTI_GET_FLAG() != RESET)
+ {
+ /* PWR PVM1 interrupt user callback */
+ HAL_PWREx_PVM1Callback();
+
+ /* Clear PVM1 exti pending bit */
+ __HAL_PWR_PVM1_EXTI_CLEAR_FLAG();
+ }
+#endif /* defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) */
+ if(__HAL_PWR_PVM2_EXTI_GET_FLAG() != RESET)
+ {
+ /* PWR PVM2 interrupt user callback */
+ HAL_PWREx_PVM2Callback();
+
+ /* Clear PVM2 exti pending bit */
+ __HAL_PWR_PVM2_EXTI_CLEAR_FLAG();
+ }
+ if(__HAL_PWR_PVM3_EXTI_GET_FLAG() != RESET)
+ {
+ /* PWR PVM3 interrupt user callback */
+ HAL_PWREx_PVM3Callback();
+
+ /* Clear PVM3 exti pending bit */
+ __HAL_PWR_PVM3_EXTI_CLEAR_FLAG();
+ }
+ if(__HAL_PWR_PVM4_EXTI_GET_FLAG() != RESET)
+ {
+ /* PWR PVM4 interrupt user callback */
+ HAL_PWREx_PVM4Callback();
+
+ /* Clear PVM4 exti pending bit */
+ __HAL_PWR_PVM4_EXTI_CLEAR_FLAG();
+ }
+}
+
+
+#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
+/**
+ * @brief PWR PVM1 interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWREx_PVM1Callback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_PWREx_PVM1Callback() API can be implemented in the user file
+ */
+}
+#endif /* defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) */
+
+/**
+ * @brief PWR PVM2 interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWREx_PVM2Callback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_PWREx_PVM2Callback() API can be implemented in the user file
+ */
+}
+
+/**
+ * @brief PWR PVM3 interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWREx_PVM3Callback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_PWREx_PVM3Callback() API can be implemented in the user file
+ */
+}
+
+/**
+ * @brief PWR PVM4 interrupt callback
+ * @retval None
+ */
+__weak void HAL_PWREx_PVM4Callback(void)
+{
+ /* NOTE : This function should not be modified; when the callback is needed,
+ HAL_PWREx_PVM4Callback() API can be implemented in the user file
+ */
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_qspi.c b/stmhal/hal/l4/src/stm32l4xx_hal_qspi.c
new file mode 100644
index 000000000..eeadc482b
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_qspi.c
@@ -0,0 +1,1981 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_qspi.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief QSPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the QuadSPI interface (QSPI).
+ * + Initialization and de-initialization functions
+ * + Indirect functional mode management
+ * + Memory-mapped functional mode management
+ * + Auto-polling functional mode management
+ * + Interrupts and flags management
+ * + DMA channel configuration for indirect functional mode
+ * + Errors management and abort functionality
+ *
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ *** Initialization ***
+ ======================
+ [..]
+ (#) As prerequisite, fill in the HAL_QSPI_MspInit() :
+ (++) Enable QuadSPI clock interface with __HAL_RCC_QSPI_CLK_ENABLE().
+ (++) Reset QuadSPI IP with __HAL_RCC_QSPI_FORCE_RESET() and __HAL_RCC_QSPI_RELEASE_RESET().
+ (++) Enable the clocks for the QuadSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
+ (++) Configure these QuadSPI pins in alternate mode using HAL_GPIO_Init().
+ (++) If interrupt mode is used, enable and configure QuadSPI global
+ interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (++) If DMA mode is used, enable the clocks for the QuadSPI DMA channel
+ with __HAL_RCC_DMAx_CLK_ENABLE(), configure DMA with HAL_DMA_Init(),
+ link it with QuadSPI handle using __HAL_LINKDMA(), enable and configure
+ DMA channel global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (#) Configure the flash size, the clock prescaler, the fifo threshold, the
+ clock mode, the sample shifting and the CS high time using the HAL_QSPI_Init() function.
+
+ *** Indirect functional mode ***
+ ================================
+ [..]
+ (#) Configure the command sequence using the HAL_QSPI_Command() or HAL_QSPI_Command_IT()
+ functions :
+ (++) Instruction phase : the mode used and if present the instruction opcode.
+ (++) Address phase : the mode used and if present the size and the address value.
+ (++) Alternate-bytes phase : the mode used and if present the size and the alternate
+ bytes values.
+ (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
+ (++) Data phase : the mode used and if present the number of bytes.
+ (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay
+ if activated.
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (#) If no data is required for the command, it is sent directly to the memory :
+ (++) In polling mode, the output of the function is done when the transfer is complete.
+ (++) In interrupt mode, HAL_QSPI_CmdCpltCallback() will be called when the transfer is complete.
+ (#) For the indirect write mode, use HAL_QSPI_Transmit(), HAL_QSPI_Transmit_DMA() or
+ HAL_QSPI_Transmit_IT() after the command configuration :
+ (++) In polling mode, the output of the function is done when the transfer is complete.
+ (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold
+ is reached and HAL_QSPI_TxCpltCallback() will be called when the transfer is complete.
+ (++) In DMA mode, HAL_QSPI_TxHalfCpltCallback() will be called at the half transfer and
+ HAL_QSPI_TxCpltCallback() will be called when the transfer is complete.
+ (#) For the indirect read mode, use HAL_QSPI_Receive(), HAL_QSPI_Receive_DMA() or
+ HAL_QSPI_Receive_IT() after the command configuration :
+ (++) In polling mode, the output of the function is done when the transfer is complete.
+ (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold
+ is reached and HAL_QSPI_RxCpltCallback() will be called when the transfer is complete.
+ (++) In DMA mode, HAL_QSPI_RxHalfCpltCallback() will be called at the half transfer and
+ HAL_QSPI_RxCpltCallback() will be called when the transfer is complete.
+
+ *** Auto-polling functional mode ***
+ ====================================
+ [..]
+ (#) Configure the command sequence and the auto-polling functional mode using the
+ HAL_QSPI_AutoPolling() or HAL_QSPI_AutoPolling_IT() functions :
+ (++) Instruction phase : the mode used and if present the instruction opcode.
+ (++) Address phase : the mode used and if present the size and the address value.
+ (++) Alternate-bytes phase : the mode used and if present the size and the alternate
+ bytes values.
+ (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
+ (++) Data phase : the mode used.
+ (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay
+ if activated.
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (++) The size of the status bytes, the match value, the mask used, the match mode (OR/AND),
+ the polling interval and the automatic stop activation.
+ (#) After the configuration :
+ (++) In polling mode, the output of the function is done when the status match is reached. The
+ automatic stop is activated to avoid an infinite loop.
+ (++) In interrupt mode, HAL_QSPI_StatusMatchCallback() will be called each time the status match is reached.
+
+ *** Memory-mapped functional mode ***
+ =====================================
+ [..]
+ (#) Configure the command sequence and the memory-mapped functional mode using the
+ HAL_QSPI_MemoryMapped() functions :
+ (++) Instruction phase : the mode used and if present the instruction opcode.
+ (++) Address phase : the mode used and the size.
+ (++) Alternate-bytes phase : the mode used and if present the size and the alternate
+ bytes values.
+ (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
+ (++) Data phase : the mode used.
+ (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay
+ if activated.
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (++) The timeout activation and the timeout period.
+ (#) After the configuration, the QuadSPI will be used as soon as an access on the AHB is done on
+ the address range. HAL_QSPI_TimeOutCallback() will be called when the timeout expires.
+
+ *** Errors management and abort functionality ***
+ ==================================================
+ [..]
+ (#) HAL_QSPI_GetError() function gives the error raised during the last operation.
+ (#) HAL_QSPI_Abort() function aborts any on-going operation and flushes the fifo.
+ (#) HAL_QSPI_GetState() function gives the current state of the HAL QuadSPI driver.
+
+ *** Workarounds linked to Silicon Limitation ***
+ ====================================================
+ [..]
+ (#) Workarounds Implemented inside HAL Driver
+ (++) Extra data written in the FIFO at the end of a read transfer
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup QSPI QSPI
+ * @brief QSPI HAL module driver
+ * @{
+ */
+#ifdef HAL_QSPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+
+/* Private define ------------------------------------------------------------*/
+/** @defgroup QSPI_Private_Constants QSPI Private Constants
+ * @{
+ */
+#define QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE ((uint32_t)0x00000000) /*!<Indirect write mode*/
+#define QSPI_FUNCTIONAL_MODE_INDIRECT_READ ((uint32_t)QUADSPI_CCR_FMODE_0) /*!<Indirect read mode*/
+#define QSPI_FUNCTIONAL_MODE_AUTO_POLLING ((uint32_t)QUADSPI_CCR_FMODE_1) /*!<Automatic polling mode*/
+#define QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED ((uint32_t)QUADSPI_CCR_FMODE) /*!<Memory-mapped mode*/
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup QSPI_Private_Macros QSPI Private Macros
+ * @{
+ */
+#define IS_QSPI_FUNCTIONAL_MODE(MODE) (((MODE) == QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE) || \
+ ((MODE) == QSPI_FUNCTIONAL_MODE_INDIRECT_READ) || \
+ ((MODE) == QSPI_FUNCTIONAL_MODE_AUTO_POLLING) || \
+ ((MODE) == QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED))
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+
+/* Private function prototypes -----------------------------------------------*/
+static void QSPI_DMARxCplt(DMA_HandleTypeDef *hdma);
+static void QSPI_DMATxCplt(DMA_HandleTypeDef *hdma);
+static void QSPI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void QSPI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void QSPI_DMAError(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Flag, FlagStatus State, uint32_t Timeout);
+static void QSPI_Config(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t FunctionalMode);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup QSPI_Exported_Functions QSPI Exported Functions
+ * @{
+ */
+
+/** @defgroup QSPI_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Initialize the QuadSPI.
+ (+) De-initialize the QuadSPI.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the QSPI mode according to the specified parameters
+ * in the QSPI_InitTypeDef and initialize the associated handle.
+ * @param hqspi: QSPI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Init(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the QSPI handle allocation */
+ if(hqspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_ALL_INSTANCE(hqspi->Instance));
+ assert_param(IS_QSPI_CLOCK_PRESCALER(hqspi->Init.ClockPrescaler));
+ assert_param(IS_QSPI_FIFO_THRESHOLD(hqspi->Init.FifoThreshold));
+ assert_param(IS_QSPI_SSHIFT(hqspi->Init.SampleShifting));
+ assert_param(IS_QSPI_FLASH_SIZE(hqspi->Init.FlashSize));
+ assert_param(IS_QSPI_CS_HIGH_TIME(hqspi->Init.ChipSelectHighTime));
+ assert_param(IS_QSPI_CLOCK_MODE(hqspi->Init.ClockMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hqspi->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_QSPI_MspInit(hqspi);
+
+ /* Configure the default timeout for the QSPI memory access */
+ HAL_QSPI_SetTimeout(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
+ }
+
+ /* Configure QSPI FIFO Threshold */
+ MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES,
+ ((hqspi->Init.FifoThreshold - 1) << POSITION_VAL(QUADSPI_CR_FTHRES)));
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout);
+
+ if(status == HAL_OK)
+ {
+ /* Configure QSPI Clock Prescaler and Sample Shift */
+ MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PRESCALER | QUADSPI_CR_SSHIFT),
+ ((hqspi->Init.ClockPrescaler << POSITION_VAL(QUADSPI_CR_PRESCALER)) |
+ hqspi->Init.SampleShifting));
+
+ /* Configure QSPI Flash Size, CS High Time and Clock Mode */
+ MODIFY_REG(hqspi->Instance->DCR, (QUADSPI_DCR_FSIZE | QUADSPI_DCR_CSHT | QUADSPI_DCR_CKMODE),
+ ((hqspi->Init.FlashSize << POSITION_VAL(QUADSPI_DCR_FSIZE)) |
+ hqspi->Init.ChipSelectHighTime | hqspi->Init.ClockMode));
+
+ /* Enable the QSPI peripheral */
+ __HAL_QSPI_ENABLE(hqspi);
+
+ /* Set QSPI error code to none */
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Initialize the QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief De-Initialize the QSPI peripheral.
+ * @param hqspi: QSPI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_DeInit(QSPI_HandleTypeDef *hqspi)
+{
+ /* Check the QSPI handle allocation */
+ if(hqspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ /* Disable the QSPI Peripheral Clock */
+ __HAL_QSPI_DISABLE(hqspi);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_QSPI_MspDeInit(hqspi);
+
+ /* Set QSPI error code to none */
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Initialize the QSPI state */
+ hqspi->State = HAL_QSPI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hqspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the QSPI MSP.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the QSPI MSP.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_MspDeInit can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup QSPI_Exported_Functions_Group2 Input and Output operation functions
+ * @brief QSPI Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Handle the interrupts.
+ (+) Handle the command sequence.
+ (+) Transmit data in blocking, interrupt or DMA mode.
+ (+) Receive data in blocking, interrupt or DMA mode.
+ (+) Manage the auto-polling functional mode.
+ (+) Manage the memory-mapped functional mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle QSPI interrupt request.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+void HAL_QSPI_IRQHandler(QSPI_HandleTypeDef *hqspi)
+{
+ __IO uint32_t *data_reg;
+ uint32_t flag = 0, itsource = 0;
+
+ /* QSPI Fifo Threshold interrupt occurred ----------------------------------*/
+ flag = __HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT);
+ itsource = __HAL_QSPI_GET_IT_SOURCE(hqspi, QSPI_IT_FT);
+
+ if((flag != RESET) && (itsource != RESET))
+ {
+ data_reg = &hqspi->Instance->DR;
+
+ if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX)
+ {
+ /* Transmission process */
+ while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != 0)
+ {
+ if (hqspi->TxXferCount > 0)
+ {
+ /* Fill the FIFO until the threshold is reached */
+ *(__IO uint8_t *)data_reg = *hqspi->pTxBuffPtr++;
+ hqspi->TxXferCount--;
+ }
+ else
+ {
+ /* No more data available for the transfer */
+ /* Disable the QSPI FIFO Threshold Interrupt */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT);
+ break;
+ }
+ }
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX)
+ {
+ /* Receiving Process */
+ while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != 0)
+ {
+ if (hqspi->RxXferCount > 0)
+ {
+ /* Read the FIFO until the threshold is reached */
+ *hqspi->pRxBuffPtr++ = *(__IO uint8_t *)data_reg;
+ hqspi->RxXferCount--;
+ }
+ else
+ {
+ /* All data have been received for the transfer */
+ /* Disable the QSPI FIFO Threshold Interrupt */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT);
+ break;
+ }
+ }
+ }
+
+ /* FIFO Threshold callback */
+ HAL_QSPI_FifoThresholdCallback(hqspi);
+ }
+
+ /* QSPI Transfer Complete interrupt occurred -------------------------------*/
+ flag = __HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_TC);
+ itsource = __HAL_QSPI_GET_IT_SOURCE(hqspi, QSPI_IT_TC);
+
+ if((flag != RESET) && (itsource != RESET))
+ {
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Disable the QSPI FIFO Threshold, Transfer Error and Transfer complete Interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT);
+
+ /* Transfer complete callback */
+ if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX)
+ {
+ /* Clear Busy bit */
+ HAL_QSPI_Abort(hqspi);
+
+ /* TX Complete callback */
+ HAL_QSPI_TxCpltCallback(hqspi);
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX)
+ {
+ data_reg = &hqspi->Instance->DR;
+ while(READ_BIT(hqspi->Instance->SR, QUADSPI_SR_FLEVEL) != 0)
+ {
+ if (hqspi->RxXferCount > 0)
+ {
+ /* Read the last data received in the FIFO until it is empty */
+ *hqspi->pRxBuffPtr++ = *(__IO uint8_t *)data_reg;
+ hqspi->RxXferCount--;
+ }
+ else
+ {
+ /* All data have been received for the transfer */
+ break;
+ }
+ }
+
+ /* Workaround - Extra data written in the FIFO at the end of a read transfer */
+ HAL_QSPI_Abort(hqspi);
+
+ /* RX Complete callback */
+ HAL_QSPI_RxCpltCallback(hqspi);
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_BUSY)
+ {
+ /* Command Complete callback */
+ HAL_QSPI_CmdCpltCallback(hqspi);
+ }
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ /* QSPI Status Match interrupt occurred ------------------------------------*/
+ flag = __HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_SM);
+ itsource = __HAL_QSPI_GET_IT_SOURCE(hqspi, QSPI_IT_SM);
+
+ if((flag != RESET) && (itsource != RESET))
+ {
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_SM);
+
+ /* Check if the automatic poll mode stop is activated */
+ if(READ_BIT(hqspi->Instance->CR, QUADSPI_CR_APMS) != 0)
+ {
+ /* Disable the QSPI Transfer Error and Status Match Interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE));
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ /* Status match callback */
+ HAL_QSPI_StatusMatchCallback(hqspi);
+ }
+
+ /* QSPI Transfer Error interrupt occurred ----------------------------------*/
+ flag = __HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_TE);
+ itsource = __HAL_QSPI_GET_IT_SOURCE(hqspi, QSPI_IT_TE);
+
+ if((flag != RESET) && (itsource != RESET))
+ {
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE);
+
+ /* Disable all the QSPI Interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_SM | QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT);
+
+ /* Set error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_TRANSFER;
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_ERROR;
+
+ /* Error callback */
+ HAL_QSPI_ErrorCallback(hqspi);
+ }
+
+ /* QSPI Timeout interrupt occurred -----------------------------------------*/
+ flag = __HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_TO);
+ itsource = __HAL_QSPI_GET_IT_SOURCE(hqspi, QSPI_IT_TO);
+
+ if((flag != RESET) && (itsource != RESET))
+ {
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TO);
+
+ /* Timeout callback */
+ HAL_QSPI_TimeOutCallback(hqspi);
+ }
+}
+
+/**
+ * @brief Set the command configuration.
+ * @param hqspi: QSPI handle
+ * @param cmd : structure that contains the command configuration information
+ * @param Timeout : Timeout duration
+ * @note This function is used only in Indirect Read or Write Modes
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Command(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_BUSY;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Call the configuration function */
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ if (cmd->DataMode == QSPI_DATA_NONE)
+ {
+ /* When there is no data phase, the transfer start as soon as the configuration is done
+ so wait until TC flag is set to go back in idle state */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ }
+ else
+ {
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Set the command configuration in interrupt mode.
+ * @param hqspi: QSPI handle
+ * @param cmd : structure that contains the command configuration information
+ * @note This function is used only in Indirect Read or Write Modes
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Command_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_BUSY;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ if (cmd->DataMode == QSPI_DATA_NONE)
+ {
+ /* When there is no data phase, the transfer start as soon as the configuration is done
+ so activate TC and TE interrupts */
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC);
+
+ /* Enable the QSPI Transfer Error Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_TC);
+ }
+
+ /* Call the configuration function */
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ if (cmd->DataMode != QSPI_DATA_NONE)
+ {
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hqspi: QSPI handle
+ * @param pData: pointer to data buffer
+ * @param Timeout : Timeout duration
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Transmit(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ __IO uint32_t *data_reg = &hqspi->Instance->DR;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if(pData != NULL )
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX;
+
+ /* Configure counters and size of the handle */
+ hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->pTxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional as indirect write */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ while(hqspi->TxXferCount > 0)
+ {
+ /* Wait until FT flag is set to send data */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_FT, SET, Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+
+ *(__IO uint8_t *)data_reg = *hqspi->pTxBuffPtr++;
+ hqspi->TxXferCount--;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Wait until TC flag is set to go back in idle state */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ /* Clear Transfer Complete bit */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Clear Busy bit */
+ status = HAL_QSPI_Abort(hqspi);
+ }
+ }
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hqspi: QSPI handle
+ * @param pData: pointer to data buffer
+ * @param Timeout : Timeout duration
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Receive(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t addr_reg = READ_REG(hqspi->Instance->AR);
+ __IO uint32_t *data_reg = &hqspi->Instance->DR;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if(pData != NULL )
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX;
+
+ /* Configure counters and size of the handle */
+ hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->pRxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional as indirect read */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Start the transfer by re-writing the address in AR register */
+ WRITE_REG(hqspi->Instance->AR, addr_reg);
+
+ while(hqspi->RxXferCount > 0)
+ {
+ /* Wait until FT or TC flag is set to read received data */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, (QSPI_FLAG_FT | QSPI_FLAG_TC), SET, Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+
+ *hqspi->pRxBuffPtr++ = *(__IO uint8_t *)data_reg;
+ hqspi->RxXferCount--;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Wait until TC flag is set to go back in idle state */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ /* Clear Transfer Complete bit */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Workaround - Extra data written in the FIFO at the end of a read transfer */
+ status = HAL_QSPI_Abort(hqspi);
+ }
+ }
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode with interrupt.
+ * @param hqspi: QSPI handle
+ * @param pData: pointer to data buffer
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Transmit_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if(pData != NULL )
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX;
+
+ /* Configure counters and size of the handle */
+ hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->pTxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional as indirect write */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC);
+
+ /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with interrupt.
+ * @param hqspi: QSPI handle
+ * @param pData: pointer to data buffer
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Receive_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t addr_reg = READ_REG(hqspi->Instance->AR);
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if(pData != NULL )
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX;
+
+ /* Configure counters and size of the handle */
+ hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->pRxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional as indirect read */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Start the transfer by re-writing the address in AR register */
+ WRITE_REG(hqspi->Instance->AR, addr_reg);
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC);
+
+ /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode with DMA.
+ * @param hqspi: QSPI handle
+ * @param pData: pointer to data buffer
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Transmit_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t *tmp;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if(pData != NULL )
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX;
+
+ /* Configure counters and size of the handle */
+ hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->pTxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional mode as indirect write */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ /* Set the QSPI DMA transfer complete callback */
+ hqspi->hdma->XferCpltCallback = QSPI_DMATxCplt;
+
+ /* Set the QSPI DMA Half transfer complete callback */
+ hqspi->hdma->XferHalfCpltCallback = QSPI_DMATxHalfCplt;
+
+ /* Set the DMA error callback */
+ hqspi->hdma->XferErrorCallback = QSPI_DMAError;
+
+ /* Configure the direction of the DMA */
+ hqspi->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH;
+ MODIFY_REG(hqspi->hdma->Instance->CCR, DMA_CCR_DIR, hqspi->hdma->Init.Direction);
+
+ /* Enable the QSPI transmit DMA Channel */
+ tmp = (uint32_t*)&pData;
+ HAL_DMA_Start_IT(hqspi->hdma, *(uint32_t*)tmp, (uint32_t)&hqspi->Instance->DR, hqspi->TxXferSize);
+
+ /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @param hqspi: QSPI handle
+ * @param pData: pointer to data buffer.
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Receive_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t *tmp;
+ uint32_t addr_reg = READ_REG(hqspi->Instance->AR);
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if(pData != NULL )
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX;
+
+ /* Configure counters and size of the handle */
+ hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1;
+ hqspi->pRxBuffPtr = pData;
+
+ /* Set the QSPI DMA transfer complete callback */
+ hqspi->hdma->XferCpltCallback = QSPI_DMARxCplt;
+
+ /* Set the QSPI DMA Half transfer complete callback */
+ hqspi->hdma->XferHalfCpltCallback = QSPI_DMARxHalfCplt;
+
+ /* Set the DMA error callback */
+ hqspi->hdma->XferErrorCallback = QSPI_DMAError;
+
+ /* Configure the direction of the DMA */
+ hqspi->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY;
+ MODIFY_REG(hqspi->hdma->Instance->CCR, DMA_CCR_DIR, hqspi->hdma->Init.Direction);
+
+ /* Enable the DMA Channel */
+ tmp = (uint32_t*)&pData;
+ HAL_DMA_Start_IT(hqspi->hdma, (uint32_t)&hqspi->Instance->DR, *(uint32_t*)tmp, hqspi->RxXferSize);
+
+ /* Configure QSPI: CCR register with functional as indirect read */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Start the transfer by re-writing the address in AR register */
+ WRITE_REG(hqspi->Instance->AR, addr_reg);
+
+ /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+/**
+ * @brief Configure the QSPI Automatic Polling Mode in blocking mode.
+ * @param hqspi: QSPI handle
+ * @param cmd: structure that contains the command configuration information.
+ * @param cfg: structure that contains the polling configuration information.
+ * @param Timeout : Timeout duration
+ * @note This function is used only in Automatic Polling Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_AutoPolling(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ assert_param(IS_QSPI_INTERVAL(cfg->Interval));
+ assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize));
+ assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure QSPI: PSMAR register with the status match value */
+ WRITE_REG(hqspi->Instance->PSMAR, cfg->Match);
+
+ /* Configure QSPI: PSMKR register with the status mask value */
+ WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask);
+
+ /* Configure QSPI: PIR register with the interval value */
+ WRITE_REG(hqspi->Instance->PIR, cfg->Interval);
+
+ /* Configure QSPI: CR register with Match mode and Automatic stop enabled
+ (otherwise there will be an infinite loop in blocking mode) */
+ MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS),
+ (cfg->MatchMode | QSPI_AUTOMATIC_STOP_ENABLE));
+
+ /* Call the configuration function */
+ cmd->NbData = cfg->StatusBytesSize;
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING);
+
+ /* Wait until SM flag is set to go back in idle state */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_SM, SET, Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_SM);
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the QSPI Automatic Polling Mode in non-blocking mode.
+ * @param hqspi: QSPI handle
+ * @param cmd: structure that contains the command configuration information.
+ * @param cfg: structure that contains the polling configuration information.
+ * @note This function is used only in Automatic Polling Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_AutoPolling_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ assert_param(IS_QSPI_INTERVAL(cfg->Interval));
+ assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize));
+ assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode));
+ assert_param(IS_QSPI_AUTOMATIC_STOP(cfg->AutomaticStop));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure QSPI: PSMAR register with the status match value */
+ WRITE_REG(hqspi->Instance->PSMAR, cfg->Match);
+
+ /* Configure QSPI: PSMKR register with the status mask value */
+ WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask);
+
+ /* Configure QSPI: PIR register with the interval value */
+ WRITE_REG(hqspi->Instance->PIR, cfg->Interval);
+
+ /* Configure QSPI: CR register with Match mode and Automatic stop mode */
+ MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS),
+ (cfg->MatchMode | cfg->AutomaticStop));
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_SM);
+
+ /* Enable the QSPI Transfer Error and status match Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE));
+
+ /* Call the configuration function */
+ cmd->NbData = cfg->StatusBytesSize;
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the Memory Mapped mode.
+ * @param hqspi: QSPI handle
+ * @param cmd: structure that contains the command configuration information.
+ * @param cfg: structure that contains the memory mapped configuration information.
+ * @note This function is used only in Memory mapped Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_MemoryMapped(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_MemoryMappedTypeDef *cfg)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ assert_param(IS_QSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_MEM_MAPPED;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure QSPI: CR register with timeout counter enable */
+ MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_TCEN, cfg->TimeOutActivation);
+
+ if (cfg->TimeOutActivation == QSPI_TIMEOUT_COUNTER_ENABLE)
+ {
+ assert_param(IS_QSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod));
+
+ /* Configure QSPI: LPTR register with the low-power timeout value */
+ WRITE_REG(hqspi->Instance->LPTR, cfg->TimeOutPeriod);
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TO);
+
+ /* Enable the QSPI TimeOut Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TO);
+ }
+
+ /* Call the configuration function */
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Transfer Error callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_ErrorCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Command completed callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_CmdCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+ __weak void HAL_QSPI_TxCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_RxHalfCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_RxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_TxHalfCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_TxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FIFO Threshold callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_FifoThresholdCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_FIFOThresholdCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Status Match callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_StatusMatchCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Timeout callback.
+ * @param hqspi: QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_TimeOutCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_TimeOutCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup QSPI_Exported_Functions_Group3 Peripheral Control and State functions
+ * @brief QSPI control and State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control and State functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Check in run-time the state of the driver.
+ (+) Check the error code set during last operation.
+ (+) Abort any operation.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the QSPI handle state.
+ * @param hqspi: QSPI handle
+ * @retval HAL state
+ */
+HAL_QSPI_StateTypeDef HAL_QSPI_GetState(QSPI_HandleTypeDef *hqspi)
+{
+ /* Return QSPI handle state */
+ return hqspi->State;
+}
+
+/**
+* @brief Return the QSPI error code.
+* @param hqspi: QSPI handle
+* @retval QSPI Error Code
+*/
+uint32_t HAL_QSPI_GetError(QSPI_HandleTypeDef *hqspi)
+{
+ return hqspi->ErrorCode;
+}
+
+/**
+* @brief Abort the current transmission.
+* @param hqspi: QSPI handle
+* @retval HAL status
+*/
+HAL_StatusTypeDef HAL_QSPI_Abort(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* Configure QSPI: CR register with Abort request */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT);
+
+ /* Wait until TC flag is set to go back in idle state */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, hqspi->Timeout) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Wait until BUSY flag is reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout);
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ return status;
+}
+
+/** @brief Set QSPI timeout.
+ * @param hqspi: QSPI handle.
+ * @param Timeout: Timeout for the QSPI memory access.
+ * @retval None
+ */
+void HAL_QSPI_SetTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Timeout)
+{
+ hqspi->Timeout = Timeout;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief DMA QSPI receive process complete callback.
+ * @param hdma: DMA handle
+ * @retval None
+ */
+static void QSPI_DMARxCplt(DMA_HandleTypeDef *hdma)
+{
+ QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ hqspi->RxXferCount = 0;
+
+ /* Wait for QSPI TC Flag */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, hqspi->Timeout) != HAL_OK)
+ {
+ /* Timeout occurred */
+ HAL_QSPI_ErrorCallback(hqspi);
+ }
+ else
+ {
+ /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Disable the DMA channel */
+ HAL_DMA_Abort(hdma);
+
+ /* Clear Transfer Complete bit */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Workaround - Extra data written in the FIFO at the end of a read transfer */
+ HAL_QSPI_Abort(hqspi);
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ HAL_QSPI_RxCpltCallback(hqspi);
+ }
+}
+
+/**
+ * @brief DMA QSPI transmit process complete callback.
+ * @param hdma: DMA handle
+ * @retval None
+ */
+static void QSPI_DMATxCplt(DMA_HandleTypeDef *hdma)
+{
+ QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ hqspi->TxXferCount = 0;
+
+ /* Wait for QSPI TC Flag */
+ if(QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, hqspi->Timeout) != HAL_OK)
+ {
+ /* Timeout occurred */
+ HAL_QSPI_ErrorCallback(hqspi);
+ }
+ else
+ {
+ /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Disable the DMA channel */
+ HAL_DMA_Abort(hdma);
+
+ /* Clear Transfer Complete bit */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Clear Busy bit */
+ HAL_QSPI_Abort(hqspi);
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ HAL_QSPI_TxCpltCallback(hqspi);
+ }
+}
+
+/**
+ * @brief DMA QSPI receive process half complete callback.
+ * @param hdma : DMA handle
+ * @retval None
+ */
+static void QSPI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ HAL_QSPI_RxHalfCpltCallback(hqspi);
+}
+
+/**
+ * @brief DMA QSPI transmit process half complete callback.
+ * @param hdma : DMA handle
+ * @retval None
+ */
+static void QSPI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ HAL_QSPI_TxHalfCpltCallback(hqspi);
+}
+
+/**
+ * @brief DMA QSPI communication error callback.
+ * @param hdma: DMA handle
+ * @retval None
+ */
+static void QSPI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ hqspi->RxXferCount = 0;
+ hqspi->TxXferCount = 0;
+ hqspi->State = HAL_QSPI_STATE_ERROR;
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+
+ HAL_QSPI_ErrorCallback(hqspi);
+}
+
+/**
+ * @brief Wait for a flag state until timeout.
+ * @param hqspi: QSPI handle
+ * @param Flag: Flag checked
+ * @param State: Value of the flag expected
+ * @param Timeout: Duration of the timeout
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Flag,
+ FlagStatus State, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Wait until flag is in expected state */
+ while((FlagStatus)(__HAL_QSPI_GET_FLAG(hqspi, Flag)) != State)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout))
+ {
+ hqspi->State = HAL_QSPI_STATE_ERROR;
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the communication registers.
+ * @param hqspi: QSPI handle
+ * @param cmd: structure that contains the command configuration information
+ * @param FunctionalMode: functional mode to configured
+ * This parameter can be one of the following values:
+ * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE: Indirect write mode
+ * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_READ: Indirect read mode
+ * @arg QSPI_FUNCTIONAL_MODE_AUTO_POLLING: Automatic polling mode
+ * @arg QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED: Memory-mapped mode
+ * @retval None
+ */
+static void QSPI_Config(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t FunctionalMode)
+{
+ assert_param(IS_QSPI_FUNCTIONAL_MODE(FunctionalMode));
+
+ if ((cmd->DataMode != QSPI_DATA_NONE) && (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED))
+ {
+ /* Configure QSPI: DLR register with the number of data to read or write */
+ WRITE_REG(hqspi->Instance->DLR, (cmd->NbData - 1));
+ }
+
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ /* Configure QSPI: ABR register with alternate bytes value */
+ WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes);
+
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with instruction, address and alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressSize | cmd->AddressMode | cmd->InstructionMode |
+ cmd->Instruction | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with instruction and alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressMode | cmd->InstructionMode |
+ cmd->Instruction | FunctionalMode));
+ }
+ }
+ else
+ {
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with instruction and address ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateByteMode | cmd->AddressSize | cmd->AddressMode |
+ cmd->InstructionMode | cmd->Instruction | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with only instruction ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateByteMode | cmd->AddressMode |
+ cmd->InstructionMode | cmd->Instruction | FunctionalMode));
+ }
+ }
+ }
+ else
+ {
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ /* Configure QSPI: ABR register with alternate bytes value */
+ WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes);
+
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with address and alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressSize | cmd->AddressMode |
+ cmd->InstructionMode | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with only alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressMode | cmd->InstructionMode | FunctionalMode));
+ }
+ }
+ else
+ {
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with only address ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateByteMode | cmd->AddressSize |
+ cmd->AddressMode | cmd->InstructionMode | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with only data phase ----*/
+ if (cmd->DataMode != QSPI_DATA_NONE)
+ {
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) |
+ cmd->AlternateByteMode | cmd->AddressMode |
+ cmd->InstructionMode | FunctionalMode));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_QSPI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_rcc.c b/stmhal/hal/l4/src/stm32l4xx_hal_rcc.c
new file mode 100644
index 000000000..514442851
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_rcc.c
@@ -0,0 +1,1439 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_rcc.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @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
+ *
+ @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) busses:
+ all peripherals mapped on these busses 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 busses 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 (SAIx, RTC, ADC, USB OTG FS/SDMMC1/RNG)
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_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 ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+#define MSI_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+#define LSI_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+#define PLL_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+#define CLOCKSWITCH_TIMEOUT_VALUE ((uint32_t)5000U) /* 5 s */
+
+#define PLLSOURCE_NONE ((uint32_t)0U)
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup RCC_Private_Macros RCC Private Macros
+ * @{
+ */
+#define __MCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
+#define MCO1_GPIO_PORT GPIOA
+#define MCO1_PIN GPIO_PIN_8
+
+#define RCC_PLL_OSCSOURCE_CONFIG(__HAL_RCC_PLLSOURCE__) \
+ (MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (uint32_t)(__HAL_RCC_PLLSOURCE__)))
+/**
+ * @}
+ */
+
+/* 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 msirange);
+/**
+ * @}
+ */
+
+/* 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, LSI, PLL, CSS and MCO) and the System busses clocks (SYSCLK, AHB, APB1
+ and APB2).
+
+ [..] 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 (Mutiple Speed Internal): Its frequency is software trimmable from 100KHZ to 48MHZ.
+ It can be used to generate the clock for the USB OTG 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.
+
+ (+) LSI (low-speed internal): 32 KHz low consumption RC used as IWDG and/or RTC
+ clock source.
+
+ (+) HSE (high-speed external): 4 to 48 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.
+
+ (+) 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 80MHz).
+ (++) The second output is used to generate the clock for the USB OTG FS (48 MHz),
+ the random analog generator (<=48 MHz) and the SDMMC1 (<= 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 ADC1 clock.
+ (++) The second output is used to generate the clock for the USB OTG FS (48 MHz),
+ the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz).
+ (++) The Third output is used to generate an accurate clock to achieve
+ high-quality audio performance on SAI interface.
+
+ (+) PLLSAI2 (clocked by HSI , HSE or MSI) providing up to two independent output clocks:
+ (++) The first output is used to generate SAR ADC2 clock.
+ (++) The second 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 HSI and an interrupt is generated if enabled.
+ The interrupt is linked to the Cortex-M4 NMI (Non-Maskable Interrupt)
+ exception vector.
+
+ (+) MCO (microcontroller clock output): used to output MSI, LSI, HSI, LSE, HSE or
+ main PLL clock (through a configurable prescaler) on PA8 pin.
+
+ [..] System, AHB and APB busses clocks configuration
+ (+) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI,
+ HSE and main PLL.
+ The AHB clock (HCLK) 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 busses. You can use
+ "HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks.
+
+ -@- 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 (PLLSAI2) 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 2 to 31.
+ You have to use __HAL_RCC_RTC_ENABLE() and HAL_RCCEx_PeriphCLKConfig() function
+ to configure this clock.
+ (+@) USB OTG FS, SDMMC1 and RNG: USB OTG FS requires a frequency equal to 48 MHz
+ to work correctly, while the SDMMC1 and RNG peripherals require 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, HCLK, PCLK1 and PCLK2 is 80 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. HCLK clock frequency.
+ +-------------------------------------------------------+
+ | Latency | HCLK clock frequency (MHz) |
+ | |-------------------------------------|
+ | | voltage range 1 | voltage range 2 |
+ | | 1.2 V | 1.0 V |
+ |-----------------|------------------|------------------|
+ |0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 |
+ |-----------------|------------------|------------------|
+ |1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 |
+ |-----------------|------------------|------------------|
+ |2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 |
+ |-----------------|------------------|------------------|
+ |3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 |
+ |-----------------|------------------|------------------|
+ |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 |
+ +-------------------------------------------------------+
+ * @{
+ */
+
+/**
+ * @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 and PLLISAI2 OFF
+ * - AHB, APB1 and APB2 prescaler set to 1.
+ * - CSS, MCO1 OFF
+ * - All interrupts disabled
+ * @note This function doesn't modify the configuration of the
+ * - Peripheral clocks
+ * - LSI, LSE and RTC clocks
+ * @retval None
+ */
+void HAL_RCC_DeInit(void)
+{
+ /* Set MSION bit */
+ SET_BIT(RCC->CR, RCC_CR_MSION);
+
+ /* Insure MSIRDY bit is set before writing default MSIRANGE value */
+ while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) { __NOP(); }
+
+ /* Set MSIRANGE default value */
+ MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6);
+
+ /* Reset CFGR register (MSI is selected as system clock source) */
+ CLEAR_REG(RCC->CFGR);
+
+ /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON);
+
+ /* Reset PLLCFGR register */
+ CLEAR_REG(RCC->PLLCFGR);
+ SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 );
+
+ /* Reset PLLSAI1CFGR register */
+ CLEAR_REG(RCC->PLLSAI1CFGR);
+ SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N_4 );
+
+ /* Reset PLLSAI2CFGR register */
+ CLEAR_REG(RCC->PLLSAI2CFGR);
+ SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N_4 );
+
+ /* Reset HSEBYP bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
+
+ /* Disable all interrupts */
+ CLEAR_REG(RCC->CIER);
+
+ /* Update the SystemCoreClock global variable */
+ SystemCoreClock = MSI_VALUE;
+}
+
+/**
+ * @brief Initialize the RCC Oscillators according to the specified parameters in the
+ * RCC_OscInitTypeDef.
+ * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
+ * contains the configuration information for the RCC Oscillators.
+ * @note The PLL is not disabled when used as system clock.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(RCC_OscInitStruct != NULL);
+ 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 */
+ if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) )
+ {
+ if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) && (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 CPU clock
+ (HCLK) 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_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> POSITION_VAL(RCC_CFGR_HPRE)];
+
+ /* Configure the source of time base considering new system clocks settings*/
+ HAL_InitTick (TICK_INT_PRIORITY);
+ }
+ }
+ 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(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET)
+ {
+ 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 ready */
+ while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET)
+ {
+ 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 */
+ if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||
+ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))
+ {
+ if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
+ {
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Reset HSEON and HSEBYP bits before configuring the HSE --------------*/
+ __HAL_RCC_HSE_CONFIG(RCC_HSE_OFF);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is disabled */
+ while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* 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(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is disabled */
+ while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET)
+ {
+ 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 */
+ if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||
+ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI)))
+ {
+ /* When HSI is used as system clock it will not be disabled */
+ if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (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(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
+ {
+ 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(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ /*------------------------------ LSI Configuration -------------------------*/
+ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
+
+ /* Check the LSI State */
+ if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
+ {
+ /* Enable the Internal Low Speed oscillator (LSI). */
+ __HAL_RCC_LSI_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI is ready */
+ while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Disable the Internal Low Speed oscillator (LSI). */
+ __HAL_RCC_LSI_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSI is disabled */
+ while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ /*------------------------------ LSE Configuration -------------------------*/
+ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
+ {
+ FlagStatus pwrclkchanged = RESET;
+
+ /* 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(RCC->APB1ENR1, RCC_APB1ENR1_PWREN))
+ {
+ __HAL_RCC_PWR_CLK_ENABLE();
+ pwrclkchanged = SET;
+ }
+
+ if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
+ {
+ /* Enable write access to Backup domain */
+ SET_BIT(PWR->CR1, PWR_CR1_DBP);
+
+ /* 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(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is disabled */
+ while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Restore clock configuration if changed */
+ if(pwrclkchanged == SET)
+ {
+ __HAL_RCC_PWR_CLK_DISABLE();
+ }
+ }
+ /*-------------------------------- PLL Configuration -----------------------*/
+ /* Check the parameters */
+ assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
+
+ if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
+ {
+ /* Check if the PLL is used as system clock or not */
+ if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
+ {
+ 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));
+
+ /* 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) != RESET)
+ {
+ 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) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Disable the main PLL. */
+ __HAL_RCC_PLL_DISABLE();
+
+ /* Disable all PLL outputs to save power */
+ MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PLLSOURCE_NONE);
+ __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is disabled */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the CPU, AHB and APB busses clocks according to the specified
+ * parameters in the RCC_ClkInitStruct.
+ * @param RCC_ClkInitStruct pointer to an RCC_OscInitTypeDef 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
+ * @arg FLASH_LATENCY_4 FLASH 4 Latency cycle
+ *
+ * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency
+ * and updated by 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 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 HCLK 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 = 0;
+
+ /* Check the parameters */
+ assert_param(RCC_ClkInitStruct != NULL);
+ 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 CPU clock
+ (HCLK) and the supply voltage of the device. */
+
+ /* Increasing the number of wait states because of higher CPU frequency */
+ if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY))
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLatency);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /*-------------------------- HCLK Configuration --------------------------*/
+ if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
+ {
+ assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
+ }
+
+ /*------------------------- 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(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* PLL is selected as System Clock Source */
+ else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
+ {
+ /* Check the PLL ready flag */
+ if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* MSI is selected as System Clock Source */
+ else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
+ {
+ /* Check the MSI ready flag */
+ if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* HSI is selected as System Clock Source */
+ else
+ {
+ /* Check the HSI ready flag */
+ if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
+ {
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE)
+ {
+ if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
+ {
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
+ {
+ if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
+ {
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_MSI)
+ {
+ if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI)
+ {
+ if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* Decreasing the number of wait states because of lower CPU frequency */
+ if(FLatency < (FLASH->ACR & FLASH_ACR_LATENCY))
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLatency);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /*-------------------------- PCLK1 Configuration ---------------------------*/
+ if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
+ {
+ assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
+ }
+
+ /*-------------------------- PCLK2 Configuration ---------------------------*/
+ if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
+ {
+ assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
+ }
+
+ /* Update the SystemCoreClock global variable */
+ SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> POSITION_VAL(RCC_CFGR_HPRE)];
+
+ /* Configure the source of time base considering new system clocks settings*/
+ HAL_InitTick (TICK_INT_PRIORITY);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @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:
+
+ (+) Ouput clock to MCO pin.
+ (+) Retrieve current clock frequencies.
+ (+) Enable the Clock Security System.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Select the clock source to output on MCO pin(PA8).
+ * @note PA8 should be configured in alternate function mode.
+ * @param RCC_MCOx specifies the output direction for the clock source.
+ * For STM32L4xx family this parameter can have only one value:
+ * @arg @ref RCC_MCO1 Clock source to output on MCO1 pin(PA8).
+ * @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 sourcee
+ * @arg @ref RCC_MCO1SOURCE_PLLCLK main PLL clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_LSI LSI clock selected as MCO source
+ * @arg @ref RCC_MCO1SOURCE_LSE LSE clock 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;
+ /* Check the parameters */
+ assert_param(IS_RCC_MCO(RCC_MCOx));
+ assert_param(IS_RCC_MCODIV(RCC_MCODiv));
+ assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
+
+ /* MCO Clock Enable */
+ __MCO1_CLK_ENABLE();
+
+ /* Configue the MCO1 pin in alternate function mode */
+ GPIO_InitStruct.Pin = MCO1_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
+ HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
+
+ /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */
+ MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv ));
+}
+
+/**
+ * @brief Return the SYSCLK frequency.
+ *
+ * @note The system frequency 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
+ * Value as defined by the 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 stm32l4xx_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 stm32l4xx_hal_conf.h file (default value
+ * 8 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 msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U;
+ uint32_t sysclockfreq = 0U;
+
+ if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ||
+ ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI)))
+ {
+ /* MSI or PLL with MSI source used as system clock source */
+
+ /* Get SYSCLK source */
+ if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET)
+ { /* MSISRANGE from RCC_CSR applies */
+ msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> POSITION_VAL(RCC_CSR_MSISRANGE);
+ }
+ else
+ { /* MSIRANGE from RCC_CR applies */
+ msirange = (RCC->CR & RCC_CR_MSIRANGE) >> POSITION_VAL(RCC_CR_MSIRANGE);
+ }
+ /*MSI frequency range in HZ*/
+ msirange = MSIRangeTable[msirange];
+
+ if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI)
+ {
+ /* MSI used as system clock source */
+ sysclockfreq = msirange;
+ }
+ }
+ else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)
+ {
+ /* HSI used as system clock source */
+ sysclockfreq = HSI_VALUE;
+ }
+ else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)
+ {
+ /* HSE used as system clock source */
+ sysclockfreq = HSE_VALUE;
+ }
+
+ if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL)
+ {
+ /* PLL used as system clock source */
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
+ SYSCLK = PLL_VCO / PLLR
+ */
+ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
+ pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> POSITION_VAL(RCC_PLLCFGR_PLLM)) + 1U ;
+
+ switch (pllsource)
+ {
+ case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+ pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN));
+ break;
+
+ case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN));
+ break;
+
+ case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
+ default:
+ pllvco = (msirange / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN));
+ break;
+ }
+ pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> POSITION_VAL(RCC_PLLCFGR_PLLR)) + 1U ) * 2U;
+ sysclockfreq = pllvco/pllr;
+ }
+
+ return sysclockfreq;
+}
+
+/**
+ * @brief Return the HCLK frequency.
+ * @note Each time HCLK changes, this function must be called to update the
+ * right HCLK value. Otherwise, any configuration based on this function will be incorrect.
+ *
+ * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency.
+ * @retval HCLK frequency in Hz
+ */
+uint32_t HAL_RCC_GetHCLKFreq(void)
+{
+ return SystemCoreClock;
+}
+
+/**
+ * @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 (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1)>> POSITION_VAL(RCC_CFGR_PPRE1)]);
+}
+
+/**
+ * @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 (HAL_RCC_GetHCLKFreq()>> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2)>> POSITION_VAL(RCC_CFGR_PPRE2)]);
+}
+
+/**
+ * @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)
+{
+ /* Check the parameters */
+ assert_param(RCC_OscInitStruct != 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_LSI;
+
+ /* Get the HSE configuration -----------------------------------------------*/
+ if((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
+ }
+ else if((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON)
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
+ }
+
+ /* Get the MSI configuration -----------------------------------------------*/
+ if((RCC->CR & RCC_CR_MSION) == RCC_CR_MSION)
+ {
+ RCC_OscInitStruct->MSIState = RCC_MSI_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->MSIState = RCC_MSI_OFF;
+ }
+
+ RCC_OscInitStruct->MSICalibrationValue = (uint32_t)((RCC->CR & RCC_ICSCR_MSITRIM) >> POSITION_VAL(RCC_ICSCR_MSITRIM));
+ RCC_OscInitStruct->MSIClockRange = (uint32_t)((RCC->CR & RCC_CR_MSIRANGE) );
+
+ /* Get the HSI configuration -----------------------------------------------*/
+ if((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
+ {
+ RCC_OscInitStruct->HSIState = RCC_HSI_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
+ }
+
+ RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> POSITION_VAL(RCC_ICSCR_HSITRIM));
+
+ /* Get the LSE configuration -----------------------------------------------*/
+ if((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
+ }
+ else if((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
+ }
+
+ /* Get the LSI configuration -----------------------------------------------*/
+ if((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION)
+ {
+ RCC_OscInitStruct->LSIState = RCC_LSI_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
+ }
+
+ /* Get the PLL configuration -----------------------------------------------*/
+ if((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON)
+ {
+ RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
+ }
+ RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
+ RCC_OscInitStruct->PLL.PLLM = (uint32_t)(((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> POSITION_VAL(RCC_PLLCFGR_PLLM)) + 1U);
+ RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN));
+ RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> POSITION_VAL(RCC_PLLCFGR_PLLQ)) + 1U) << 1U);
+ RCC_OscInitStruct->PLL.PLLR = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> POSITION_VAL(RCC_PLLCFGR_PLLR)) + 1U) << 1U);
+ if((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) != RESET)
+ {
+ RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17;
+ }
+ else
+ {
+ RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7;
+ }
+}
+
+/**
+ * @brief Configure the RCC_ClkInitStruct according to the internal
+ * RCC configuration registers.
+ * @param RCC_ClkInitStruct pointer to an 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 != NULL);
+ assert_param(pFLatency != 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;
+
+ /* Get the SYSCLK configuration --------------------------------------------*/
+ RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW);
+
+ /* Get the HCLK configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE);
+
+ /* Get the APB1 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1);
+
+ /* Get the APB2 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3U);
+
+ /* Get the Flash Wait State (Latency) configuration ------------------------*/
+ *pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_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
+ * the Cortex-M4 NMI (Non-Maskable Interrupt) exception vector.
+ * @note The Clock Security System can only be cleared by reset.
+ * @retval None
+ */
+void HAL_RCC_EnableCSS(void)
+{
+ SET_BIT(RCC->CR, RCC_CR_CSSON) ;
+}
+
+/**
+ * @brief Handle the RCC 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_CSS))
+ {
+ /* RCC Clock Security System interrupt user callback */
+ HAL_RCC_CSSCallback();
+
+ /* Clear RCC CSS pending bit */
+ __HAL_RCC_CLEAR_IT(RCC_IT_CSS);
+ }
+}
+
+/**
+ * @brief RCC 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 HAL_RCC_CSSCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup RCC_Private_Functions
+ * @{
+ */
+/**
+ * @brief Update number of Flash wait states in line with MSI range and current
+ voltage range.
+ * @param msirange MSI range value from RCC_MSIRANGE_0 to RCC_MSIRANGE_11
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange)
+{
+ uint32_t vos = 0;
+ uint32_t latency = FLASH_LATENCY_0; /* default value 0WS */
+
+ if(__HAL_RCC_PWR_IS_CLK_ENABLED())
+ {
+ vos = HAL_PWREx_GetVoltageRange();
+ }
+ else
+ {
+ __HAL_RCC_PWR_CLK_ENABLE();
+ vos = HAL_PWREx_GetVoltageRange();
+ __HAL_RCC_PWR_CLK_DISABLE();
+ }
+
+ if(vos == PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ if(msirange > RCC_MSIRANGE_8)
+ {
+ /* MSI > 16Mhz */
+ if(msirange > RCC_MSIRANGE_10)
+ {
+ /* MSI 48Mhz */
+ latency = FLASH_LATENCY_2; /* 2WS */
+ }
+ else
+ {
+ /* MSI 24Mhz or 32Mhz */
+ latency = FLASH_LATENCY_1; /* 1WS */
+ }
+ }
+ /* else MSI <= 16Mhz default FLASH_LATENCY_0 0WS */
+ }
+ else
+ {
+ if(msirange > RCC_MSIRANGE_8)
+ {
+ /* MSI > 16Mhz */
+ latency = FLASH_LATENCY_3; /* 3WS */
+ }
+ else
+ {
+ if(msirange == RCC_MSIRANGE_8)
+ {
+ /* MSI 16Mhz */
+ latency = FLASH_LATENCY_2; /* 2WS */
+ }
+ else if(msirange == RCC_MSIRANGE_7)
+ {
+ /* MSI 8Mhz */
+ latency = FLASH_LATENCY_1; /* 1WS */
+ }
+ /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */
+ }
+ }
+
+ __HAL_FLASH_SET_LATENCY(latency);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if((FLASH->ACR & FLASH_ACR_LATENCY) != latency)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_rcc_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_rcc_ex.c
new file mode 100644
index 000000000..4c32c0a17
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_rcc_ex.c
@@ -0,0 +1,2009 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_rcc_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief Extended RCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities RCC extended peripheral:
+ * + Extended Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_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
+ * @{
+ */
+#define PLLSAI1_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+#define PLLSAI2_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+#define PLL_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */
+
+#define __LSCO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
+#define LSCO_GPIO_PORT GPIOA
+#define LSCO_PIN GPIO_PIN_2
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup RCCEx_Private_Functions RCCEx Private Functions
+ * @{
+ */
+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);
+static HAL_StatusTypeDef RCCEx_PLLSAI2_ConfigNP(RCC_PLLSAI2InitTypeDef *PllSai2);
+static HAL_StatusTypeDef RCCEx_PLLSAI2_ConfigNR(RCC_PLLSAI2InitTypeDef *PllSai2);
+/**
+ * @}
+ */
+
+/* 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 RCC_PeriphCLKInitTypeDef.
+ * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
+ * contains a field PeriphClockSelection which can be a combination of the following values:
+ * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
+ * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
+ * @arg @ref RCC_PERIPHCLK_DFSDM DFSDM peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C2 I2C2 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_SAI2 SAI2 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
+ *
+ * @note Care must be taken when 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 tmpregister = 0;
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */
+ HAL_StatusTypeDef status = HAL_OK; /* Final status */
+
+ /* Check the parameters */
+ assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
+
+ /*-------------------------- 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 SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK);
+ /* 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_PLLSAI2: /* PLLSAI2 is used as clock source for SAI1*/
+ /* PLLSAI2 parameters N & P configuration and clock output (PLLSAI2ClockOut) */
+ ret = RCCEx_PLLSAI2_ConfigNP(&(PeriphClkInit->PLLSAI2));
+ /* 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;
+
+ 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;
+ }
+ }
+
+ /*-------------------------- SAI2 clock source configuration ---------------------*/
+ if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection));
+
+ switch(PeriphClkInit->Sai2ClockSelection)
+ {
+ case RCC_SAI2CLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/
+ /* Enable SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK);
+ /* SAI2 clock source config set later after clock selection check */
+ break;
+
+ case RCC_SAI2CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI2*/
+ /* PLLSAI1 parameters N & P configuration and clock output (PLLSAI1ClockOut) */
+ ret = RCCEx_PLLSAI1_ConfigNP(&(PeriphClkInit->PLLSAI1));
+ /* SAI2 clock source config set later after clock selection check */
+ break;
+
+ case RCC_SAI2CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI2*/
+ /* PLLSAI2 parameters N & P configuration and clock output (PLLSAI2ClockOut) */
+ ret = RCCEx_PLLSAI2_ConfigNP(&(PeriphClkInit->PLLSAI2));
+ /* SAI2 clock source config set later after clock selection check */
+ break;
+
+ case RCC_SAI2CLKSOURCE_PIN: /* External clock is used as source of SAI2 clock*/
+ /* SAI2 clock source config set later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if(ret == HAL_OK)
+ {
+ /* Set the source of SAI2 clock*/
+ __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*-------------------------- RTC clock source configuration ----------------------*/
+ if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
+ {
+ FlagStatus pwrclkchanged = RESET;
+
+ /* Check for RTC Parameters used to output RTCCLK */
+ assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
+
+ /* Enable Power Clock */
+ if(__HAL_RCC_PWR_IS_CLK_DISABLED())
+ {
+ __HAL_RCC_PWR_CLK_ENABLE();
+ pwrclkchanged = SET;
+ }
+
+ /* Enable write access to Backup domain */
+ SET_BIT(PWR->CR1, PWR_CR1_DBP);
+
+ /* Wait for Backup domain Write protection disable */
+ tickstart = HAL_GetTick();
+
+ while((PWR->CR1 & PWR_CR1_DBP) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
+ {
+ ret = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(ret == HAL_OK)
+ {
+ /* Reset the Backup domain only if the RTC Clock source selection is modified */
+ if(READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL) != PeriphClkInit->RTCClockSelection)
+ {
+ /* Store the content of BDCR register before the reset of Backup Domain */
+ tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
+ /* RTC Clock selection can be changed only if the Backup Domain is reset */
+ __HAL_RCC_BACKUPRESET_FORCE();
+ __HAL_RCC_BACKUPRESET_RELEASE();
+ /* Restore the Content of BDCR register */
+ RCC->BDCR = tmpregister;
+ }
+
+ /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
+ if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSERDY))
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ ret = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+
+ if(ret == HAL_OK)
+ {
+ /* Apply new RTC clock source selection */
+ __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+
+ /* Restore clock configuration if changed */
+ if(pwrclkchanged == SET)
+ {
+ __HAL_RCC_PWR_CLK_DISABLE();
+ }
+ }
+
+ /*-------------------------- 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);
+ }
+
+ /*-------------------------- USART2 clock source configuration -------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection));
+
+ /* Configure the USART2 clock source */
+ __HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection);
+ }
+
+ /*-------------------------- USART3 clock source configuration -------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection));
+
+ /* Configure the USART3 clock source */
+ __HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection);
+ }
+
+ /*-------------------------- UART4 clock source configuration --------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_UART4CLKSOURCE(PeriphClkInit->Uart4ClockSelection));
+
+ /* Configure the UART4 clock source */
+ __HAL_RCC_UART4_CONFIG(PeriphClkInit->Uart4ClockSelection);
+ }
+
+ /*-------------------------- UART5 clock source configuration --------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_UART5CLKSOURCE(PeriphClkInit->Uart5ClockSelection));
+
+ /* Configure the UART5 clock source */
+ __HAL_RCC_UART5_CONFIG(PeriphClkInit->Uart5ClockSelection);
+ }
+
+ /*-------------------------- 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);
+ }
+
+ /*-------------------------- 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);
+ }
+
+ /*-------------------------- I2C2 clock source configuration ---------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C2CLKSOURCE(PeriphClkInit->I2c2ClockSelection));
+
+ /* Configure the I2C2 clock source */
+ __HAL_RCC_I2C2_CONFIG(PeriphClkInit->I2c2ClockSelection);
+ }
+
+ /*-------------------------- 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);
+ }
+
+#if defined(USB_OTG_FS)
+
+ /*-------------------------- 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 PLL48M1CLK output */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
+ }
+ else 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 /* USB_OTG_FS */
+
+ /*-------------------------- SDMMC1 clock source configuration -------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1))
+ {
+ assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection));
+ __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection);
+
+ if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL)
+ {
+ /* Enable PLL48M1CLK output */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
+ }
+ else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_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;
+ }
+ }
+ }
+
+ /*-------------------------- RNG clock source configuration ----------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG))
+ {
+ assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection));
+ __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection);
+
+ if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL)
+ {
+ /* Enable PLL48M1CLK output */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
+ }
+ else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_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;
+ }
+ }
+ }
+
+ /*-------------------------- 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_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;
+ }
+ }
+ else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2)
+ {
+ /* PLLSAI2 parameters N & R configuration and clock output (PLLSAI2ClockOut) */
+ ret = RCCEx_PLLSAI2_ConfigNR(&(PeriphClkInit->PLLSAI2));
+
+ if(ret != HAL_OK)
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+ }
+
+ /*-------------------------- SWPMI1 clock source configuration -------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection));
+
+ /* Configure the SWPMI1 clock source */
+ __HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection);
+ }
+
+ /*-------------------------- DFSDM clock source configuration --------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM) == RCC_PERIPHCLK_DFSDM)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_DFSDMCLKSOURCE(PeriphClkInit->DfsdmClockSelection));
+
+ /* Configure the DFSDM interface clock source */
+ __HAL_RCC_DFSDM_CONFIG(PeriphClkInit->DfsdmClockSelection);
+ }
+
+ 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, SAI2, LPTIM1, LPTIM2, I2C1, I2C2, I2C3, LPUART,
+ * USART1, USART2, USART3, UART4, UART5, RTC, ADCx, DFSDMx, SWPMI1, USB, SDMMC1 and RNG).
+ * @retval None
+ */
+void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ /* Set all possible values for the extended clock type parameter------------*/
+
+#if defined(STM32L471xx)
+
+ PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
+ RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
+ RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | \
+ RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM | \
+ RCC_PERIPHCLK_RTC ;
+
+#else
+
+ PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
+ RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
+ RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \
+ RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM | \
+ RCC_PERIPHCLK_RTC ;
+
+#endif /* STM32L471xx */
+
+ /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLLSAI1.PLLSAI1N = (uint32_t)((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1N) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1N));
+ PeriphClkInit->PLLSAI1.PLLSAI1P = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1P) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1P)) << 4U) + 7U;
+ PeriphClkInit->PLLSAI1.PLLSAI1R = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1R) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1R))+1U) * 2U;
+ PeriphClkInit->PLLSAI1.PLLSAI1Q = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1Q) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1Q))+1U) * 2U;
+
+ /* Get the PLLSAI2 Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2N) >> POSITION_VAL(RCC_PLLSAI2CFGR_PLLSAI2N));
+ PeriphClkInit->PLLSAI2.PLLSAI2P = (uint32_t)(((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2P) >> POSITION_VAL(RCC_PLLSAI2CFGR_PLLSAI2P)) << 4U) + 7U;
+ PeriphClkInit->PLLSAI2.PLLSAI2R = (uint32_t)(((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2R)>> POSITION_VAL(RCC_PLLSAI2CFGR_PLLSAI2R))+1U) * 2U;
+
+ /* Get the USART1 clock source ---------------------------------------------*/
+ PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
+ /* Get the USART2 clock source ---------------------------------------------*/
+ PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE();
+ /* Get the USART3 clock source ---------------------------------------------*/
+ PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE();
+ /* Get the UART4 clock source ----------------------------------------------*/
+ PeriphClkInit->Uart4ClockSelection = __HAL_RCC_GET_UART4_SOURCE();
+ /* Get the UART5 clock source ----------------------------------------------*/
+ PeriphClkInit->Uart5ClockSelection = __HAL_RCC_GET_UART5_SOURCE();
+ /* Get the LPUART1 clock source --------------------------------------------*/
+ PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE();
+ /* Get the I2C1 clock source -----------------------------------------------*/
+ PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
+ /* Get the I2C2 clock source ----------------------------------------------*/
+ PeriphClkInit->I2c2ClockSelection = __HAL_RCC_GET_I2C2_SOURCE();
+ /* Get the I2C3 clock source -----------------------------------------------*/
+ PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE();
+ /* Get the LPTIM1 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
+ /* Get the LPTIM2 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE();
+ /* Get the SAI1 clock source -----------------------------------------------*/
+ PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();
+ /* Get the SAI2 clock source -----------------------------------------------*/
+ PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE();
+ /* Get the RTC clock source ------------------------------------------------*/
+ PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
+
+#if defined(USB_OTG_FS)
+ /* Get the USB clock source ------------------------------------------------*/
+ PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
+#endif /* USB_OTG_FS */
+
+ /* Get the SDMMC1 clock source ---------------------------------------------*/
+ PeriphClkInit->Sdmmc1ClockSelection = __HAL_RCC_GET_SDMMC1_SOURCE();
+ /* Get the RNG clock source ------------------------------------------------*/
+ PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE();
+ /* Get the ADC clock source -----------------------------------------------*/
+ PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
+ /* Get the SWPMI1 clock source ----------------------------------------------*/
+ PeriphClkInit->Swpmi1ClockSelection = __HAL_RCC_GET_SWPMI1_SOURCE();
+ /* Get the DFSDM clock source -------------------------------------------*/
+ PeriphClkInit->DfsdmClockSelection = __HAL_RCC_GET_DFSDM_SOURCE();
+}
+
+/**
+ * @brief Return the peripheral clock frequency for peripherals with clock source from PLLSAIs
+ * @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_DFSDM DFSDM peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_I2C2 I2C2 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_SAI2 SAI2 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock
+ * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
+ * @retval Frequency in Hz
+ */
+uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
+{
+ uint32_t frequency = 0U;
+ uint32_t srcclk = 0;
+ uint32_t pllvco = 0, plln = 0, pllp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
+
+ if(PeriphClk == RCC_PERIPHCLK_RTC)
+ {
+ /* Get the current RTC source */
+ srcclk = __HAL_RCC_GET_RTC_SOURCE();
+
+ /* Check if LSE is ready and if RTC clock selection is LSE */
+ if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Check if LSI is ready and if RTC clock selection is LSI */
+ else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
+ {
+ frequency = LSI_VALUE;
+ }
+ /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/
+ else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)))
+ {
+ frequency = HSE_VALUE / 32;
+ }
+ /* Clock not enabled for RTC*/
+ else
+ {
+ frequency = 0U;
+ }
+ }
+ else
+ {
+ /* Other external peripheral clock source than RTC */
+
+ /* Compute PLL clock input */
+ if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) /* MSI ? */
+ {
+ pllvco = (1U << ((__HAL_RCC_GET_MSI_RANGE() >> 4U) - 4U)) * 1000000U;
+ }
+ else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI) /* HSI ? */
+ {
+ pllvco = HSI_VALUE;
+ }
+ else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) /* HSE ? */
+ {
+ pllvco = HSE_VALUE;
+ }
+ else /* No source */
+ {
+ pllvco = 0;
+ }
+
+ /* f(PLL Source) / PLLM */
+ pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> POSITION_VAL(RCC_PLLCFGR_PLLM)) + 1U));
+
+ switch(PeriphClk)
+ {
+ case RCC_PERIPHCLK_SAI1:
+ case RCC_PERIPHCLK_SAI2:
+
+ if(PeriphClk == RCC_PERIPHCLK_SAI1)
+ {
+ srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI1SEL);
+
+ if(srcclk == RCC_SAI1CLKSOURCE_PIN)
+ {
+ frequency = EXTERNAL_SAI1_CLOCK_VALUE;
+ }
+ /* Else, PLL clock output to check below */
+ }
+ else /* RCC_PERIPHCLK_SAI2 */
+ {
+ srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI2SEL);
+
+ if(srcclk == RCC_SAI2CLKSOURCE_PIN)
+ {
+ frequency = EXTERNAL_SAI2_CLOCK_VALUE;
+ }
+ /* Else, PLL clock output to check below */
+ }
+
+ if(frequency == 0U)
+ {
+ if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL))
+ {
+ if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET)
+ {
+ /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */
+ plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN);
+ if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET)
+ {
+ pllp = 17U;
+ }
+ else
+ {
+ pllp = 7U;
+ }
+ frequency = (pllvco * plln) / pllp;
+ }
+ }
+ else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */
+ {
+ if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET)
+ {
+ /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */
+ plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1N);
+ if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET)
+ {
+ pllp = 17U;
+ }
+ else
+ {
+ pllp = 7U;
+ }
+ frequency = (pllvco * plln) / pllp;
+ }
+ }
+ else if((srcclk == RCC_SAI1CLKSOURCE_PLLSAI2) || (srcclk == RCC_SAI2CLKSOURCE_PLLSAI2))
+ {
+ if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_SAI2CLK) != RESET)
+ {
+ /* f(PLLSAI2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2P */
+ plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> POSITION_VAL(RCC_PLLSAI2CFGR_PLLSAI2N);
+ if(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) != RESET)
+ {
+ pllp = 17U;
+ }
+ else
+ {
+ pllp = 7U;
+ }
+ frequency = (pllvco * plln) / pllp;
+ }
+ }
+ else
+ {
+ /* No clock source */
+ frequency = 0U;
+ }
+ }
+ break;
+
+#if defined(USB_OTG_FS)
+
+ case RCC_PERIPHCLK_USB:
+
+#endif /* USB_OTG_FS */
+
+ case RCC_PERIPHCLK_RNG:
+ case RCC_PERIPHCLK_SDMMC1:
+
+ srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL);
+
+ if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */
+ {
+ frequency = (1U << ((__HAL_RCC_GET_MSI_RANGE() >> 4U) - 4U)) * 1000000U;
+ }
+ else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL ? */
+ {
+ /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */
+ plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN);
+ frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> POSITION_VAL(RCC_PLLCFGR_PLLQ)) + 1U) << 1U);
+ }
+ else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */
+ {
+ /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */
+ plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1N);
+ frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1Q)) + 1U) << 1U);
+ }
+ else /* No clock source */
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_USART1:
+ /* Get the current USART1 source */
+ srcclk = __HAL_RCC_GET_USART1_SOURCE();
+
+ if(srcclk == RCC_USART1CLKSOURCE_PCLK2)
+ {
+ frequency = HAL_RCC_GetPCLK2Freq();
+ }
+ else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for USART1 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_USART2:
+ /* Get the current USART2 source */
+ srcclk = __HAL_RCC_GET_USART2_SOURCE();
+
+ if(srcclk == RCC_USART2CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_USART2CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for USART2 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_USART3:
+ /* Get the current USART3 source */
+ srcclk = __HAL_RCC_GET_USART3_SOURCE();
+
+ if(srcclk == RCC_USART3CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_USART3CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for USART3 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_UART4:
+ /* Get the current UART4 source */
+ srcclk = __HAL_RCC_GET_UART4_SOURCE();
+
+ if(srcclk == RCC_UART4CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_UART4CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_UART4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if((srcclk == RCC_UART4CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for UART4 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_UART5:
+ /* Get the current UART5 source */
+ srcclk = __HAL_RCC_GET_UART5_SOURCE();
+
+ if(srcclk == RCC_UART5CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_UART5CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_UART5CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if((srcclk == RCC_UART5CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for UART5 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_LPUART1:
+ /* Get the current LPUART1 source */
+ srcclk = __HAL_RCC_GET_LPUART1_SOURCE();
+
+ if(srcclk == RCC_LPUART1CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_LPUART1CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_LPUART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if((srcclk == RCC_LPUART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for LPUART1 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_ADC:
+
+ srcclk = __HAL_RCC_GET_ADC_SOURCE();
+
+ if(srcclk == RCC_ADCCLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI1)
+ {
+ if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != RESET)
+ {
+ /* f(PLLADC1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1R */
+ plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1N);
+ frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> POSITION_VAL(RCC_PLLSAI1CFGR_PLLSAI1R)) + 1U) << 1U);
+ }
+ }
+ else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI2)
+ {
+ if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != RESET)
+ {
+ /* f(PLLADC2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2R */
+ plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> POSITION_VAL(RCC_PLLSAI2CFGR_PLLSAI2N);
+ frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> POSITION_VAL(RCC_PLLSAI2CFGR_PLLSAI2R)) + 1U) << 1U);
+ }
+ }
+ /* Clock not enabled for ADC */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_DFSDM:
+ /* Get the current DFSDM source */
+ srcclk = __HAL_RCC_GET_DFSDM_SOURCE();
+
+ if(srcclk == RCC_DFSDMCLKSOURCE_PCLK)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ break;
+
+ case RCC_PERIPHCLK_I2C1:
+ /* Get the current I2C1 source */
+ srcclk = __HAL_RCC_GET_I2C1_SOURCE();
+
+ if(srcclk == RCC_I2C1CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_I2C1CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ /* Clock not enabled for I2C1 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_I2C2:
+ /* Get the current I2C2 source */
+ srcclk = __HAL_RCC_GET_I2C2_SOURCE();
+
+ if(srcclk == RCC_I2C2CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_I2C2CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_I2C2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ /* Clock not enabled for I2C2 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_I2C3:
+ /* Get the current I2C3 source */
+ srcclk = __HAL_RCC_GET_I2C3_SOURCE();
+
+ if(srcclk == RCC_I2C3CLKSOURCE_PCLK1)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if(srcclk == RCC_I2C3CLKSOURCE_SYSCLK)
+ {
+ frequency = HAL_RCC_GetSysClockFreq();
+ }
+ else if((srcclk == RCC_I2C3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ /* Clock not enabled for I2C3 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_LPTIM1:
+ /* Get the current LPTIM1 source */
+ srcclk = __HAL_RCC_GET_LPTIM1_SOURCE();
+
+ if(srcclk == RCC_LPTIM1CLKSOURCE_PCLK)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
+ {
+ frequency = LSI_VALUE;
+ }
+ else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if ((srcclk == RCC_LPTIM1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for LPTIM1 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_LPTIM2:
+ /* Get the current LPTIM2 source */
+ srcclk = __HAL_RCC_GET_LPTIM2_SOURCE();
+
+ if(srcclk == RCC_LPTIM2CLKSOURCE_PCLK)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
+ {
+ frequency = LSI_VALUE;
+ }
+ else if((srcclk == RCC_LPTIM2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ else if ((srcclk == RCC_LPTIM2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
+ {
+ frequency = LSE_VALUE;
+ }
+ /* Clock not enabled for LPTIM2 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ case RCC_PERIPHCLK_SWPMI1:
+ /* Get the current SWPMI1 source */
+ srcclk = __HAL_RCC_GET_SWPMI1_SOURCE();
+
+ if(srcclk == RCC_SWPMI1CLKSOURCE_PCLK)
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ }
+ else if((srcclk == RCC_SWPMI1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
+ {
+ frequency = HSI_VALUE;
+ }
+ /* Clock not enabled for SWPMI1 */
+ else
+ {
+ frequency = 0U;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return(frequency);
+}
+
+/**
+ * @}
+ */
+
+/** @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, PLLSAI2, LSE CSS,
+ Low speed clock output and clock after wake-up from STOP mode.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @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 = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLSAI1N_VALUE(PLLSAI1Init->PLLSAI1N));
+ assert_param(IS_RCC_PLLSAI1P_VALUE(PLLSAI1Init->PLLSAI1P));
+ assert_param(IS_RCC_PLLSAI1Q_VALUE(PLLSAI1Init->PLLSAI1Q));
+ assert_param(IS_RCC_PLLSAI1R_VALUE(PLLSAI1Init->PLLSAI1R));
+ 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
+ {
+ 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->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R);
+ /* 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
+ {
+ 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 = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Disable the PLLSAI1 */
+ __HAL_RCC_PLLSAI1_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI1 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
+ {
+ 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_48M2CLK|RCC_PLLSAI1_ADC1CLK);
+
+ return status;
+}
+
+/**
+ * @brief Enable PLLSAI2.
+ * @param PLLSAI2Init pointer to an RCC_PLLSAI2InitTypeDef structure that
+ * contains the configuration information for the PLLSAI2
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init)
+{
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */
+ assert_param(IS_RCC_PLLSAI2N_VALUE(PLLSAI2Init->PLLSAI2N));
+ assert_param(IS_RCC_PLLSAI2P_VALUE(PLLSAI2Init->PLLSAI2P));
+ assert_param(IS_RCC_PLLSAI2R_VALUE(PLLSAI2Init->PLLSAI2R));
+ assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PLLSAI2Init->PLLSAI2ClockOut));
+
+ /* Disable the PLLSAI2 */
+ __HAL_RCC_PLLSAI2_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready to be updated */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Configure the PLLSAI2 Multiplication factor N */
+ /* Configure the PLLSAI2 Division factors P and R */
+ __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R);
+ /* Configure the PLLSAI2 Clock output(s) */
+ __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PLLSAI2Init->PLLSAI2ClockOut);
+
+ /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/
+ __HAL_RCC_PLLSAI2_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable PLLISAI2.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void)
+{
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Disable the PLLSAI2 */
+ __HAL_RCC_PLLSAI2_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ /* Disable the PLLSAI2 Clock outputs */
+ __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2_SAI2CLK|RCC_PLLSAI2_ADC2CLK);
+
+ return status;
+}
+
+/**
+ * @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 Configure the MSI range after standby mode.
+ * @note After Standby its frequency can be selected between 4 possible values (1, 2, 4 or 8 MHz).
+ * @param MSIRange MSI range
+ * This parameter can be one of the following values:
+ * @arg @ref RCC_MSIRANGE_4 Range 4 around 1 MHz
+ * @arg @ref RCC_MSIRANGE_5 Range 5 around 2 MHz
+ * @arg @ref RCC_MSIRANGE_6 Range 6 around 4 MHz (reset value)
+ * @arg @ref RCC_MSIRANGE_7 Range 7 around 8 MHz
+ * @retval None
+ */
+void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange)
+{
+ assert_param(IS_RCC_MSI_STANDBY_CLOCK_RANGE(MSIRange));
+
+ __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(MSIRange);
+}
+
+/**
+ * @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)
+{
+ SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
+}
+
+/**
+ * @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)
+{
+ CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
+
+ /* 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 19
+ * @retval None
+ */
+void HAL_RCCEx_EnableLSECSS_IT(void)
+{
+ /* Enable LSE CSS */
+ SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
+
+ /* Enable LSE CSS IT */
+ __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
+
+ /* Enable IT on EXTI Line 19 */
+ __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 @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file
+ */
+}
+
+/**
+ * @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)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ FlagStatus pwrclkchanged = RESET;
+ FlagStatus backupchanged = RESET;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_LSCOSOURCE(LSCOSource));
+
+ /* LSCO Pin Clock Enable */
+ __LSCO_CLK_ENABLE();
+
+ /* Configue the LSCO pin in analog mode */
+ GPIO_InitStruct.Pin = LSCO_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(LSCO_GPIO_PORT, &GPIO_InitStruct);
+
+ /* Update LSCOSEL clock source in Backup Domain control register */
+ if(__HAL_RCC_PWR_IS_CLK_DISABLED())
+ {
+ __HAL_RCC_PWR_CLK_ENABLE();
+ pwrclkchanged = SET;
+ }
+ if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
+ {
+ HAL_PWR_EnableBkUpAccess();
+ backupchanged = SET;
+ }
+
+ MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL | RCC_BDCR_LSCOEN, LSCOSource | RCC_BDCR_LSCOEN);
+
+ if(backupchanged == SET)
+ {
+ HAL_PWR_DisableBkUpAccess();
+ }
+ if(pwrclkchanged == SET)
+ {
+ __HAL_RCC_PWR_CLK_DISABLE();
+ }
+}
+
+/**
+ * @brief Disable the Low Speed clock output.
+ * @retval None
+ */
+void HAL_RCCEx_DisableLSCO(void)
+{
+ FlagStatus pwrclkchanged = RESET;
+ FlagStatus backupchanged = RESET;
+
+ /* Update LSCOEN bit in Backup Domain control register */
+ if(__HAL_RCC_PWR_IS_CLK_DISABLED())
+ {
+ __HAL_RCC_PWR_CLK_ENABLE();
+ pwrclkchanged = SET;
+ }
+ if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
+ {
+ /* Enable access to the backup domain */
+ HAL_PWR_EnableBkUpAccess();
+ backupchanged = SET;
+ }
+
+ CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSCOEN);
+
+ /* Restore previous configuration */
+ if(backupchanged == SET)
+ {
+ /* Disable access to the backup domain */
+ HAL_PWR_DisableBkUpAccess();
+ }
+ if(pwrclkchanged == SET)
+ {
+ __HAL_RCC_PWR_CLK_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 HAL_RCC_OscConfig().
+ * @retval None
+ */
+void HAL_RCCEx_EnableMSIPLLMode(void)
+{
+ SET_BIT(RCC->CR, RCC_CR_MSIPLLEN) ;
+}
+
+/**
+ * @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)
+{
+ CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup RCCEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @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 = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N));
+ assert_param(IS_RCC_PLLSAI1P_VALUE(PllSai1->PLLSAI1P));
+ 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
+ {
+ 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->PLLSAI1N);
+ /* Configure the PLLSAI1 Division factor P */
+ __HAL_RCC_PLLSAI1_DIVP_CONFIG(PllSai1->PLLSAI1P);
+
+ /* 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
+ {
+ 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 = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N));
+ assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q));
+ 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
+ {
+ 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->PLLSAI1N);
+ /* Configure the PLLSAI1 Division factor Q */
+ __HAL_RCC_PLLSAI1_DIVQ_CONFIG(PllSai1->PLLSAI1Q);
+
+ /* 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
+ {
+ 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 = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
+ assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N));
+ assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R));
+ 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
+ {
+ 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->PLLSAI1N);
+ /* Configure the PLLSAI1 Division factor R */
+ __HAL_RCC_PLLSAI1_DIVR_CONFIG(PllSai1->PLLSAI1R);
+
+ /* 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(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
+ {
+ 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 & P of PLLSAI2 and enable PLLSAI2 output clock(s).
+ * @param PllSai2 pointer to an RCC_PLLSAI2InitTypeDef structure that
+ * contains the configuration parameters N & P as well as PLLSAI2 output clock(s)
+ *
+ * @note PLLSAI2 is temporary disable to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLLSAI2_ConfigNP(RCC_PLLSAI2InitTypeDef *PllSai2)
+{
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI2 Parameters */
+ assert_param(IS_RCC_PLLSAI2N_VALUE(PllSai2->PLLSAI2N));
+ assert_param(IS_RCC_PLLSAI2P_VALUE(PllSai2->PLLSAI2P));
+ assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PllSai2->PLLSAI2ClockOut));
+
+ /* Disable the PLLSAI2 */
+ __HAL_RCC_PLLSAI2_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Configure the PLLSAI2 Multiplication factor N */
+ __HAL_RCC_PLLSAI2_MULN_CONFIG(PllSai2->PLLSAI2N);
+ /* Configure the PLLSAI2 Division factor P */
+ __HAL_RCC_PLLSAI2_DIVP_CONFIG(PllSai2->PLLSAI2P);
+
+ /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/
+ __HAL_RCC_PLLSAI2_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Configure the PLLSAI2 Clock output(s) */
+ __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PllSai2->PLLSAI2ClockOut);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Configure the parameters N & R of PLLSAI2 and enable PLLSAI2 output clock(s).
+ * @param PllSai2 pointer to an RCC_PLLSAI2InitTypeDef structure that
+ * contains the configuration parameters N & R as well as PLLSAI2 output clock(s)
+ *
+ * @note PLLSAI2 is temporary disable to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLLSAI2_ConfigNR(RCC_PLLSAI2InitTypeDef *PllSai2)
+{
+ uint32_t tickstart = 0U;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check for PLLSAI2 Parameters */
+ assert_param(IS_RCC_PLLSAI2N_VALUE(PllSai2->PLLSAI2N));
+ assert_param(IS_RCC_PLLSAI2R_VALUE(PllSai2->PLLSAI2R));
+ assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PllSai2->PLLSAI2ClockOut));
+
+ /* Disable the PLLSAI2 */
+ __HAL_RCC_PLLSAI2_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Configure the PLLSAI2 Multiplication factor N */
+ __HAL_RCC_PLLSAI2_MULN_CONFIG(PllSai2->PLLSAI2N);
+ /* Configure the PLLSAI2 Division factor R */
+ __HAL_RCC_PLLSAI2_DIVR_CONFIG(PllSai2->PLLSAI2R);
+
+ /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/
+ __HAL_RCC_PLLSAI2_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI2 is ready */
+ while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
+ {
+ status = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if(status == HAL_OK)
+ {
+ /* Configure the PLLSAI2 Clock output(s) */
+ __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PllSai2->PLLSAI2ClockOut);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_rng.c b/stmhal/hal/l4/src/stm32l4xx_hal_rng.c
new file mode 100644
index 000000000..8dd1fc3b6
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_rng.c
@@ -0,0 +1,519 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_rng.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief RNG HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Random Number Generator (RNG) peripheral:
+ * + Initialization/de-initialization functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The RNG HAL driver can be used as follows:
+
+ (#) Enable the RNG controller clock using __HAL_RCC_RNG_CLK_ENABLE() macro
+ in HAL_RNG_MspInit().
+ (#) Activate the RNG peripheral using HAL_RNG_Init() function.
+ (#) Wait until the 32-bit Random Number Generator contains a valid
+ random data using (polling/interrupt) mode.
+ (#) Get the 32 bit random number using HAL_RNG_GenerateRandomNumber() function.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RNG RNG
+ * @brief RNG HAL module driver.
+ * @{
+ */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+
+
+
+/* Private types -------------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup RNG_Private_Constants RNG_Private_Constants
+ * @{
+ */
+#define RNG_TIMEOUT_VALUE 2
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup RNG_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup RNG_Exported_Functions_Group1
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize the RNG according to the specified parameters
+ in the RNG_InitTypeDef and create the associated handle
+ (+) DeInitialize the RNG peripheral
+ (+) Initialize the RNG MSP (MCU Specific Package)
+ (+) DeInitialize the RNG MSP
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the RNG peripheral and initialize the associated handle.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng)
+{
+ /* Check the RNG handle allocation */
+ if(hrng == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance));
+
+ __HAL_LOCK(hrng);
+
+ if(hrng->State == HAL_RNG_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrng->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware */
+ HAL_RNG_MspInit(hrng);
+ }
+
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Enable the RNG Peripheral */
+ __HAL_RNG_ENABLE(hrng);
+
+ /* Initialize the RNG state */
+ hrng->State = HAL_RNG_STATE_READY;
+
+ __HAL_UNLOCK(hrng);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the RNG peripheral.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng)
+{
+ /* Check the RNG handle allocation */
+ if(hrng == NULL)
+ {
+ return HAL_ERROR;
+ }
+ /* Disable the RNG Peripheral */
+ CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN);
+
+ /* Clear RNG interrupt status flags */
+ CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS);
+
+ /* DeInit the low level hardware */
+ HAL_RNG_MspDeInit(hrng);
+
+ /* Update the RNG state */
+ hrng->State = HAL_RNG_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrng);
+
+ /* Return the function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the RNG MSP.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval None
+ */
+__weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_MspInit must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief DeInitialize the RNG MSP.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval None
+ */
+__weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_MspDeInit must be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RNG_Exported_Functions_Group2
+ * @brief Management functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Get the 32 bit Random number
+ (+) Get the 32 bit Random number with interrupt enabled
+ (+) Handle RNG interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Generate a 32-bit random number.
+ * @note Each time the random number data is read the RNG_FLAG_DRDY flag
+ * is automatically cleared.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @param random32bit: pointer to generated random number variable if successful.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit)
+{
+ uint32_t tickstart = 0;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hrng);
+
+ /* Check RNS peripheral state */
+ if(hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if data register contains valid random data */
+ while(__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RNG_TIMEOUT_VALUE)
+ {
+ hrng->State = HAL_RNG_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Get a 32bit Random number */
+ hrng->RandomNumber = hrng->Instance->DR;
+ *random32bit = hrng->RandomNumber;
+
+ hrng->State = HAL_RNG_STATE_READY;
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+ return status;
+}
+
+/**
+ * @brief Generate a 32-bit random number in interrupt mode.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hrng);
+
+ /* Check RNG peripheral state */
+ if(hrng->State == HAL_RNG_STATE_READY)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+ /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */
+ __HAL_RNG_ENABLE_IT(hrng);
+ }
+ else
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrng);
+
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handle RNG interrupt request.
+ * @note In the case of a clock error, the RNG is no more able to generate
+ * random numbers because the PLL48CLK clock is not correct. User has
+ * to check that the clock controller is correctly configured to provide
+ * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT().
+ * The clock error has no impact on the previously generated
+ * random numbers, and the RNG_DR register contents can be used.
+ * @note In the case of a seed error, the generation of random numbers is
+ * interrupted as long as the SECS bit is '1'. If a number is
+ * available in the RNG_DR register, it must not be used because it may
+ * not have enough entropy. In this case, it is recommended to clear the
+ * SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable
+ * the RNG peripheral to reinitialize and restart the RNG.
+ * @note User-written HAL_RNG_ErrorCallback() API is called once whether SEIS
+ * or CEIS are set.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval None
+
+ */
+void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng)
+{
+ /* RNG clock error interrupt occurred */
+ if((__HAL_RNG_GET_IT(hrng, RNG_IT_CEI) != RESET) || (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET))
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_ERROR;
+
+ HAL_RNG_ErrorCallback(hrng);
+
+ /* Clear the clock error flag */
+ __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI|RNG_IT_SEI);
+
+ }
+
+ /* Check RNG data ready interrupt occurred */
+ if(__HAL_RNG_GET_IT(hrng, RNG_IT_DRDY) != RESET)
+ {
+ /* Generate random number once, so disable the IT */
+ __HAL_RNG_DISABLE_IT(hrng);
+
+ /* Get the 32bit Random number (DRDY flag automatically cleared) */
+ hrng->RandomNumber = hrng->Instance->DR;
+
+ if(hrng->State != HAL_RNG_STATE_ERROR)
+ {
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_READY;
+
+ /* Data Ready callback */
+ HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber);
+ }
+ }
+}
+
+/**
+ * @brief Return generated random number in polling mode (Obsolete).
+ * @note Use HAL_RNG_GenerateRandomNumber() API instead.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval random value
+ */
+uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng)
+{
+ if(HAL_RNG_GenerateRandomNumber(hrng, &(hrng->RandomNumber)) == HAL_OK)
+ {
+ return hrng->RandomNumber;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/**
+ * @brief Return a 32-bit random number with interrupt enabled (Obsolete).
+ * @note Use HAL_RNG_GenerateRandomNumber_IT() API instead.
+ * @param hrng: RNG handle
+ * @retval 32-bit random number
+ */
+uint32_t HAL_RNG_GetRandomNumber_IT(RNG_HandleTypeDef *hrng)
+{
+ uint32_t random32bit = 0;
+
+ /* Process locked */
+ __HAL_LOCK(hrng);
+
+ /* Change RNG peripheral state */
+ hrng->State = HAL_RNG_STATE_BUSY;
+
+ /* Get a 32bit Random number */
+ random32bit = hrng->Instance->DR;
+
+ /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */
+ __HAL_RNG_ENABLE_IT(hrng);
+
+ /* Return the 32 bit random number */
+ return random32bit;
+}
+
+
+
+/**
+ * @brief Read latest generated random number.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval random value
+ */
+uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng)
+{
+ return(hrng->RandomNumber);
+}
+
+/**
+ * @brief Data Ready callback in non-blocking mode.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @param random32bit: generated random value
+ * @retval None
+ */
+__weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+ UNUSED(random32bit);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_ReadyDataCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @brief RNG error callback.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval None
+ */
+__weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrng);
+
+ /* NOTE : This function should not be modified. When the callback is needed,
+ function HAL_RNG_ErrorCallback must be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup RNG_Exported_Functions_Group3
+ * @brief Peripheral State functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the RNG handle state.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure.
+ * @retval HAL state
+ */
+HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng)
+{
+ /* Return RNG handle state */
+ return hrng->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+#endif /* HAL_RNG_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_rtc.c b/stmhal/hal/l4/src/stm32l4xx_hal_rtc.c
new file mode 100644
index 000000000..d26116342
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_rtc.c
@@ -0,0 +1,1530 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_rtc.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real-Time Clock (RTC) peripheral:
+ * + Initialization
+ * + Calendar (Time and Date) configuration
+ * + Alarms (Alarm A and Alarm B) configuration
+ * + WakeUp Timer configuration
+ * + TimeStamp configuration
+ * + Tampers configuration
+ * + Backup Data Registers configuration
+ * + RTC Tamper and TimeStamp Pins Selection
+ * + Interrupts and flags management
+ *
+ @verbatim
+ ===============================================================================
+ ##### RTC Operating Condition #####
+ ===============================================================================
+ [..] The real-time clock (RTC) and the RTC backup registers can be powered
+ from the VBAT voltage when the main VDD supply is powered off.
+ To retain the content of the RTC backup registers and supply the RTC
+ when VDD is turned off, VBAT pin can be connected to an optional
+ standby voltage supplied by a battery or by another source.
+
+ ##### Backup Domain Reset #####
+ ===============================================================================
+ [..] The backup domain reset sets all RTC registers and the RCC_BDCR register
+ to their reset values.
+ A backup domain reset is generated when one of the following events occurs:
+ (#) Software reset, triggered by setting the BDRST bit in the
+ RCC Backup domain control register (RCC_BDCR).
+ (#) VDD or VBAT power on, if both supplies have previously been powered off.
+ (#) Tamper detection event resets all data backup registers.
+
+ ##### Backup Domain Access #####
+ ===================================================================
+ [..] After reset, the backup domain (RTC registers, RTC backup data
+ registers and backup SRAM) is protected against possible unwanted write
+ accesses.
+
+ [..] To enable access to the RTC Domain and RTC registers, proceed as follows:
+ (#) Call the function HAL_RCCEx_PeriphCLKConfig with RCC_PERIPHCLK_RTC for
+ PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSEdiv32)
+ (#) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() macro.
+
+ ##### How to use RTC Driver #####
+ ===================================================================
+ [..]
+ (#) Enable the RTC domain access (see description in the section above).
+ (#) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** Time and Date configuration ***
+ ===================================
+ [..]
+ (#) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
+ and HAL_RTC_SetDate() functions.
+ (#) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions.
+
+ *** Alarm configuration ***
+ ===========================
+ [..]
+ (#) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function.
+ You can also configure the RTC Alarm with interrupt mode using the
+ HAL_RTC_SetAlarm_IT() function.
+ (#) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function.
+
+ ##### RTC and low power modes #####
+ ===================================================================
+ [..] The MCU can be woken up from a low power mode by an RTC alternate
+ function.
+ [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B),
+ RTC wakeup, RTC tamper event detection and RTC time stamp event detection.
+ These RTC alternate functions can wake up the system from the Stop and
+ Standby low power modes.
+ [..] The system can also wake up from low power modes without depending
+ on an external interrupt (Auto-wakeup mode), by using the RTC alarm
+ or the RTC wakeup events.
+ [..] The RTC provides a programmable time base for waking up from the
+ Stop or Standby mode at regular intervals.
+ Wakeup from STOP and Standby modes is possible only when the RTC clock source
+ is LSE or LSI.
+
+ @endverbatim
+
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RTC RTC
+ * @brief RTC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup RTC_Exported_Functions RTC Exported Functions
+ * @{
+ */
+
+/** @defgroup RTC_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provide functions allowing to initialize and configure the
+ RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable
+ RTC registers Write protection, enter and exit the RTC initialization mode,
+ RTC registers synchronization check and reference clock detection enable.
+ (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base.
+ It is split into 2 programmable prescalers to minimize power consumption.
+ (++) A 7-bit asynchronous prescaler and a 15-bit synchronous prescaler.
+ (++) When both prescalers are used, it is recommended to configure the
+ asynchronous prescaler to a high value to minimize power consumption.
+ (#) All RTC registers are Write protected. Writing to the RTC registers
+ is enabled by writing a key into the Write Protection register, RTC_WPR.
+ (#) To configure the RTC Calendar, user application should enter
+ initialization mode. In this mode, the calendar counter is stopped
+ and its value can be updated. When the initialization sequence is
+ complete, the calendar restarts counting after 4 RTCCLK cycles.
+ (#) To read the calendar through the shadow registers after Calendar
+ initialization, calendar update or after wakeup from low power modes
+ the software must first clear the RSF flag. The software must then
+ wait until it is set again before reading the calendar, which means
+ that the calendar registers have been correctly copied into the
+ RTC_TR and RTC_DR shadow registers. The HAL_RTC_WaitForSynchro() function
+ implements the above software sequence (RSF clear and RSF check).
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the RTC according to the specified parameters
+ * in the RTC_InitTypeDef structure and initialize the associated handle.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
+{
+ /* Check the RTC peripheral state */
+ if(hrtc == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
+ assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat));
+ assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv));
+ assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv));
+ assert_param(IS_RTC_OUTPUT(hrtc->Init.OutPut));
+ assert_param(IS_RTC_OUTPUT_REMAP(hrtc->Init.OutPutRemap));
+ assert_param(IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity));
+ assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType));
+
+ if(hrtc->State == HAL_RTC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hrtc->Lock = HAL_UNLOCKED;
+
+ /* Initialize RTC MSP */
+ HAL_RTC_MspInit(hrtc);
+ }
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Clear RTC_CR FMT, OSEL and POL Bits */
+ hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL));
+ /* Set RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity);
+
+ /* Configure the RTC PRER */
+ hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv);
+ hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16);
+
+ /* Exit Initialization mode */
+ hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT);
+
+ hrtc->Instance->OR &= (uint32_t)~(RTC_OR_ALARMOUTTYPE | RTC_OR_OUT_RMP);
+ hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType | hrtc->Init.OutPutRemap);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief DeInitialize the RTC peripheral.
+ * @param hrtc: RTC handle
+ * @note This function doesn't reset the RTC Backup Data registers.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Reset TR, DR and CR registers */
+ hrtc->Instance->TR = (uint32_t)0x00000000;
+ hrtc->Instance->DR = ((uint32_t)(RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0));
+ /* Reset All CR bits except CR[2:0] */
+ hrtc->Instance->CR &= RTC_CR_WUCKSEL;
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till WUTWF flag is set and if Time out is reached exit */
+ while(((hrtc->Instance->ISR) & RTC_ISR_WUTWF) == (uint32_t)RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Reset all RTC CR register bits */
+ hrtc->Instance->CR &= (uint32_t)0x00000000;
+ hrtc->Instance->WUTR = RTC_WUTR_WUT;
+ hrtc->Instance->PRER = ((uint32_t)(RTC_PRER_PREDIV_A | 0x000000FF));
+ hrtc->Instance->ALRMAR = (uint32_t)0x00000000;
+ hrtc->Instance->ALRMBR = (uint32_t)0x00000000;
+ hrtc->Instance->SHIFTR = (uint32_t)0x00000000;
+ hrtc->Instance->CALR = (uint32_t)0x00000000;
+ hrtc->Instance->ALRMASSR = (uint32_t)0x00000000;
+ hrtc->Instance->ALRMBSSR = (uint32_t)0x00000000;
+
+ /* Reset ISR register and exit initialization mode */
+ hrtc->Instance->ISR = (uint32_t)0x00000000;
+
+ /* Reset Tamper configuration register */
+ hrtc->Instance->TAMPCR = 0x00000000;
+
+ /* Reset Option register */
+ hrtc->Instance->OR = 0x00000000;
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* De-Initialize RTC MSP */
+ HAL_RTC_MspDeInit(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the RTC MSP.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the RTC MSP.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group2 RTC Time and Date functions
+ * @brief RTC Time and Date functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Time and Date functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Time and Date features
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set RTC current time.
+ * @param hrtc: RTC handle
+ * @param sTime: Pointer to Time structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving));
+ assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
+ {
+ assert_param(IS_RTC_HOUR12(sTime->Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
+ }
+ else
+ {
+ sTime->TimeFormat = 0x00;
+ assert_param(IS_RTC_HOUR24(sTime->Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sTime->Minutes));
+ assert_param(IS_RTC_SECONDS(sTime->Seconds));
+
+ tmpreg = (uint32_t)(((uint32_t)RTC_ByteToBcd2(sTime->Hours) << 16) | \
+ ((uint32_t)RTC_ByteToBcd2(sTime->Minutes) << 8) | \
+ ((uint32_t)RTC_ByteToBcd2(sTime->Seconds)) | \
+ (((uint32_t)sTime->TimeFormat) << 16));
+ }
+ else
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
+ {
+ tmpreg = RTC_Bcd2ToByte(sTime->Hours);
+ assert_param(IS_RTC_HOUR12(tmpreg));
+ assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat));
+ }
+ else
+ {
+ sTime->TimeFormat = 0x00;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
+ }
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
+ tmpreg = (((uint32_t)(sTime->Hours) << 16) | \
+ ((uint32_t)(sTime->Minutes) << 8) | \
+ ((uint32_t)sTime->Seconds) | \
+ ((uint32_t)(sTime->TimeFormat) << 16));
+ }
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Set the RTC_TR register */
+ hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK);
+
+ /* Clear the bits to be configured */
+ hrtc->Instance->CR &= ((uint32_t)~RTC_CR_BCK);
+
+ /* Configure the RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation);
+
+ /* Exit Initialization mode */
+ hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT);
+
+ /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Get RTC current time.
+ * @param hrtc: RTC handle
+ * @param sTime: Pointer to Time structure with Hours, Minutes and Seconds fields returned
+ * with input format (BIN or BCD), also SubSeconds field returning the
+ * RTC_SSR register content and SecondFraction field the Synchronous pre-scaler
+ * factor to be used for second fraction ratio computation.
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You can use SubSeconds and SecondFraction (sTime structure fields returned) to convert SubSeconds
+ * value in second fraction ratio with time unit following generic formula:
+ * Second fraction ratio * time_unit= [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit
+ * This conversion can be performed only if no shift operation is pending (ie. SHFP=0) when PREDIV_S >= SS
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values
+ * in the higher-order calendar shadow registers to ensure consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers until Current date is read
+ * to ensure consistency between the time and date values.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get subseconds structure field from the corresponding register*/
+ sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR);
+
+ /* Get SecondFraction structure field from the corresponding register field*/
+ sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S);
+
+ /* Get the TR register */
+ tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK);
+
+ /* Fill the structure fields with the read parameters */
+ sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
+ sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8);
+ sTime->Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU));
+ sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> 16);
+
+ /* Check the input parameters format */
+ if(Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the time structure parameters to Binary format */
+ sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours);
+ sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes);
+ sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set RTC current date.
+ * @param hrtc: RTC handle
+ * @param sDate: Pointer to date structure
+ * @param Format: specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if((Format == RTC_FORMAT_BIN) && ((sDate->Month & 0x10) == 0x10))
+ {
+ sDate->Month = (uint8_t)((sDate->Month & (uint8_t)~(0x10)) + (uint8_t)0x0A);
+ }
+
+ assert_param(IS_RTC_WEEKDAY(sDate->WeekDay));
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ assert_param(IS_RTC_YEAR(sDate->Year));
+ assert_param(IS_RTC_MONTH(sDate->Month));
+ assert_param(IS_RTC_DATE(sDate->Date));
+
+ datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year) << 16) | \
+ ((uint32_t)RTC_ByteToBcd2(sDate->Month) << 8) | \
+ ((uint32_t)RTC_ByteToBcd2(sDate->Date)) | \
+ ((uint32_t)sDate->WeekDay << 13));
+ }
+ else
+ {
+ assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year)));
+ datetmpreg = RTC_Bcd2ToByte(sDate->Month);
+ assert_param(IS_RTC_MONTH(datetmpreg));
+ datetmpreg = RTC_Bcd2ToByte(sDate->Date);
+ assert_param(IS_RTC_DATE(datetmpreg));
+
+ datetmpreg = ((((uint32_t)sDate->Year) << 16) | \
+ (((uint32_t)sDate->Month) << 8) | \
+ ((uint32_t)sDate->Date) | \
+ (((uint32_t)sDate->WeekDay) << 13));
+ }
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state*/
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Set the RTC_DR register */
+ hrtc->Instance->DR = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK);
+
+ /* Exit Initialization mode */
+ hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT);
+
+ /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY ;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Get RTC current date.
+ * @param hrtc: RTC handle
+ * @param sDate: Pointer to Date structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values
+ * in the higher-order calendar shadow registers to ensure consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers until Current date is read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get the DR register */
+ datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK);
+
+ /* Fill the structure fields with the read parameters */
+ sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> 16);
+ sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> 8);
+ sDate->Date = (uint8_t)(datetmpreg & (RTC_DR_DT | RTC_DR_DU));
+ sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> 13);
+
+ /* Check the input parameters format */
+ if(Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the date structure parameters to Binary format */
+ sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year);
+ sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month);
+ sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group3 RTC Alarm functions
+ * @brief RTC Alarm functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Alarm functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Alarm feature
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Set the specified RTC Alarm.
+ * @param hrtc: RTC handle
+ * @param sAlarm: Pointer to Alarm structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
+{
+ uint32_t tickstart = 0;
+ uint32_t tmpreg = 0, subsecondtmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(sAlarm->Alarm));
+ assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask));
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
+ {
+ assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00;
+ assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
+ assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay));
+ }
+
+ tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << 16) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << 8) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << 24) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ else
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
+ {
+ tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours);
+ assert_param(IS_RTC_HOUR12(tmpreg));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(tmpreg));
+ }
+ else
+ {
+ tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(tmpreg));
+ }
+
+ tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << 16) | \
+ ((uint32_t)(sAlarm->AlarmTime.Minutes) << 8) | \
+ ((uint32_t) sAlarm->AlarmTime.Seconds) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \
+ ((uint32_t)(sAlarm->AlarmDateWeekDay) << 24) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+
+ /* Configure the Alarm A or Alarm B Sub Second registers */
+ subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Alarm register */
+ if(sAlarm->Alarm == RTC_ALARM_A)
+ {
+ /* Disable the Alarm A interrupt */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMAR = (uint32_t)tmpreg;
+ /* Configure the Alarm A Sub Second register */
+ hrtc->Instance->ALRMASSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMA_ENABLE(hrtc);
+ }
+ else
+ {
+ /* Disable the Alarm B interrupt */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMBR = (uint32_t)tmpreg;
+ /* Configure the Alarm B Sub Second register */
+ hrtc->Instance->ALRMBSSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMB_ENABLE(hrtc);
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the specified RTC Alarm with Interrupt.
+ * @param hrtc: RTC handle
+ * @param sAlarm: Pointer to Alarm structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note The Alarm register can only be written when the corresponding Alarm
+ * is disabled (Use the HAL_RTC_DeactivateAlarm()).
+ * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
+{
+ uint32_t tickstart = 0;
+ uint32_t tmpreg = 0, subsecondtmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(sAlarm->Alarm));
+ assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask));
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds));
+ assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
+ {
+ assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00;
+ assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
+ }
+ assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
+ assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay));
+ }
+ tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << 16) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << 8) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \
+ ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << 24) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ else
+ {
+ if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET)
+ {
+ tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours);
+ assert_param(IS_RTC_HOUR12(tmpreg));
+ assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat));
+ }
+ else
+ {
+ sAlarm->AlarmTime.TimeFormat = 0x00;
+ assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
+ assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
+
+ if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE)
+ {
+ tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(tmpreg));
+ }
+ else
+ {
+ tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(tmpreg));
+ }
+ tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << 16) | \
+ ((uint32_t)(sAlarm->AlarmTime.Minutes) << 8) | \
+ ((uint32_t) sAlarm->AlarmTime.Seconds) | \
+ ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \
+ ((uint32_t)(sAlarm->AlarmDateWeekDay) << 24) | \
+ ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \
+ ((uint32_t)sAlarm->AlarmMask));
+ }
+ /* Configure the Alarm A or Alarm B Sub Second registers */
+ subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Alarm register */
+ if(sAlarm->Alarm == RTC_ALARM_A)
+ {
+ /* Disable the Alarm A interrupt */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* Clear flag alarm A */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMAR = (uint32_t)tmpreg;
+ /* Configure the Alarm A Sub Second register */
+ hrtc->Instance->ALRMASSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMA_ENABLE(hrtc);
+ /* Configure the Alarm interrupt */
+ __HAL_RTC_ALARM_ENABLE_IT(hrtc,RTC_IT_ALRA);
+ }
+ else
+ {
+ /* Disable the Alarm B interrupt */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* Clear flag alarm B */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hrtc->Instance->ALRMBR = (uint32_t)tmpreg;
+ /* Configure the Alarm B Sub Second register */
+ hrtc->Instance->ALRMBSSR = subsecondtmpreg;
+ /* Configure the Alarm state: Enable Alarm */
+ __HAL_RTC_ALARMB_ENABLE(hrtc);
+ /* Configure the Alarm interrupt */
+ __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRB);
+ }
+
+ /* RTC Alarm Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_ALARM_EXTI_ENABLE_IT();
+
+ __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate the specified RTC Alarm.
+ * @param hrtc: RTC handle
+ * @param Alarm: Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: AlarmA
+ * @arg RTC_ALARM_B: AlarmB
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALARM(Alarm));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ if(Alarm == RTC_ALARM_A)
+ {
+ /* AlarmA */
+ __HAL_RTC_ALARMA_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET)
+ {
+ if( (HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* AlarmB */
+ __HAL_RTC_ALARMB_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_ALARM_DISABLE_IT(hrtc,RTC_IT_ALRB);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the RTC Alarm value and masks.
+ * @param hrtc: RTC handle
+ * @param sAlarm: Pointer to Date structure
+ * @param Alarm: Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: AlarmA
+ * @arg RTC_ALARM_B: AlarmB
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format)
+{
+ uint32_t tmpreg = 0, subsecondtmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+ assert_param(IS_RTC_ALARM(Alarm));
+
+ if(Alarm == RTC_ALARM_A)
+ {
+ /* AlarmA */
+ sAlarm->Alarm = RTC_ALARM_A;
+
+ tmpreg = (uint32_t)(hrtc->Instance->ALRMAR);
+ subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMASSR ) & RTC_ALRMASSR_SS);
+ }
+ else
+ {
+ sAlarm->Alarm = RTC_ALARM_B;
+
+ tmpreg = (uint32_t)(hrtc->Instance->ALRMBR);
+ subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMBSSR) & RTC_ALRMBSSR_SS);
+ }
+
+ /* Fill the structure with the read parameters */
+ /* ALRMAR/ALRMBR registers have same mapping) */
+ sAlarm->AlarmTime.Hours = (uint32_t)((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> 16);
+ sAlarm->AlarmTime.Minutes = (uint32_t)((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> 8);
+ sAlarm->AlarmTime.Seconds = (uint32_t)(tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU));
+ sAlarm->AlarmTime.TimeFormat = (uint32_t)((tmpreg & RTC_ALRMAR_PM) >> 16);
+ sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg;
+ sAlarm->AlarmDateWeekDay = (uint32_t)((tmpreg & (RTC_ALRMAR_DT | RTC_ALRMAR_DU)) >> 24);
+ sAlarm->AlarmDateWeekDaySel = (uint32_t)(tmpreg & RTC_ALRMAR_WDSEL);
+ sAlarm->AlarmMask = (uint32_t)(tmpreg & RTC_ALARMMASK_ALL);
+
+ if(Format == RTC_FORMAT_BIN)
+ {
+ sAlarm->AlarmTime.Hours = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours);
+ sAlarm->AlarmTime.Minutes = RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes);
+ sAlarm->AlarmTime.Seconds = RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds);
+ sAlarm->AlarmDateWeekDay = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle Alarm interrupt request.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef* hrtc)
+{
+ /* Get the AlarmA interrupt source enable status */
+ if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET)
+ {
+ /* Get the pending status of the AlarmA Interrupt */
+ if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)
+ {
+ /* AlarmA callback */
+ HAL_RTC_AlarmAEventCallback(hrtc);
+
+ /* Clear the AlarmA interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+ }
+ }
+
+ /* Get the AlarmB interrupt source enable status */
+ if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != RESET)
+ {
+ /* Get the pending status of the AlarmB Interrupt */
+ if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != RESET)
+ {
+ /* AlarmB callback */
+ HAL_RTCEx_AlarmBEventCallback(hrtc);
+
+ /* Clear the AlarmB interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+ }
+ }
+
+ /* Clear the EXTI's line Flag for RTC Alarm */
+ __HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Alarm A callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTC_AlarmAEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handle AlarmA Polling request.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Alarm interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group4 Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Wait for RTC Time and Date Synchronization
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Wait until the RTC Time and Date registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ * @note The RTC Resynchronization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @note To read the calendar through the shadow registers after Calendar
+ * initialization, calendar update or after wakeup from low power modes
+ * the software must first clear the RSF flag.
+ * The software must then wait until it is set again before reading
+ * the calendar, which means that the calendar registers have been
+ * correctly copied into the RTC_TR and RTC_DR shadow registers.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc)
+{
+ uint32_t tickstart = 0;
+
+ /* Clear RSF flag */
+ hrtc->Instance->ISR &= (uint32_t)RTC_RSF_MASK;
+
+ tickstart = HAL_GetTick();
+
+ /* Wait the registers to be synchronised */
+ while((hrtc->Instance->ISR & RTC_ISR_RSF) == (uint32_t)RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Exported_Functions_Group5 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Get RTC state
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Return the RTC handle state.
+ * @param hrtc: RTC handle
+ * @retval HAL state
+ */
+HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef* hrtc)
+{
+ /* Return RTC handle state */
+ return hrtc->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Private_Functions RTC Private functions
+ * @{
+ */
+/**
+ * @brief Enter the RTC Initialization mode.
+ * @note The RTC Initialization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc)
+{
+ uint32_t tickstart = 0;
+
+ /* Check if the Initialization mode is set */
+ if((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
+ {
+ /* Set the Initialization mode */
+ hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK;
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC is in INIT state and if Time out is reached exit */
+ while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Convert a 2 digit decimal to BCD format.
+ * @param Value: Byte to be converted
+ * @retval Converted byte
+ */
+uint8_t RTC_ByteToBcd2(uint8_t Value)
+{
+ uint32_t bcdhigh = 0;
+
+ while(Value >= 10)
+ {
+ bcdhigh++;
+ Value -= 10;
+ }
+
+ return ((uint8_t)(bcdhigh << 4) | Value);
+}
+
+/**
+ * @brief Convert from 2 digit BCD to Binary.
+ * @param Value: BCD value to be converted
+ * @retval Converted word
+ */
+uint8_t RTC_Bcd2ToByte(uint8_t Value)
+{
+ uint32_t tmp = 0;
+ tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;
+ return (tmp + (Value & (uint8_t)0x0F));
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RTC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_rtc_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_rtc_ex.c
new file mode 100644
index 000000000..510f9e2a7
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_rtc_ex.c
@@ -0,0 +1,1876 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_rtc_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief Extended RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real Time Clock (RTC) Extended peripheral:
+ * + RTC Time Stamp functions
+ * + RTC Tamper functions
+ * + RTC Wake-up functions
+ * + Extended Control functions
+ * + Extended RTC features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (+) Enable the RTC domain access.
+ (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** RTC Wakeup configuration ***
+ ================================
+ [..]
+ (+) To configure the RTC Wakeup Clock source and Counter use the HAL_RTCEx_SetWakeUpTimer()
+ function. You can also configure the RTC Wakeup timer with interrupt mode
+ using the HAL_RTCEx_SetWakeUpTimer_IT() function.
+ (+) To read the RTC WakeUp Counter register, use the HAL_RTCEx_GetWakeUpTimer()
+ function.
+
+ *** Outputs configuration ***
+ =============================
+ [..] The RTC has 2 different outputs:
+ (+) RTC_ALARM: this output is used to manage the RTC Alarm A, Alarm B
+ and WaKeUp signals.
+ To output the selected RTC signal, use the HAL_RTC_Init() function.
+ (+) RTC_CALIB: this output is 512Hz signal or 1Hz.
+ To enable the RTC_CALIB, use the HAL_RTCEx_SetCalibrationOutPut() function.
+ (+) Two pins can be used as RTC_ALARM or RTC_CALIB (PC13, PB2) managed on
+ the RTC_OR register.
+ (+) When the RTC_CALIB or RTC_ALARM output is selected, the RTC_OUT pin is
+ automatically configured in output alternate function.
+
+ *** Smooth digital Calibration configuration ***
+ ================================================
+ [..]
+ (+) Configure the RTC Original Digital Calibration Value and the corresponding
+ calibration cycle period (32s,16s and 8s) using the HAL_RTCEx_SetSmoothCalib()
+ function.
+
+ *** TimeStamp configuration ***
+ ===============================
+ [..]
+ (+) Enable the RTC TimeStamp using the HAL_RTCEx_SetTimeStamp() function.
+ You can also configure the RTC TimeStamp with interrupt mode using the
+ HAL_RTCEx_SetTimeStamp_IT() function.
+ (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp()
+ function.
+
+ *** Internal TimeStamp configuration ***
+ ===============================
+ [..]
+ (+) Enable the RTC internal TimeStamp using the HAL_RTCEx_SetInternalTimeStamp() function.
+ User has to check internal timestamp occurrence using __HAL_RTC_INTERNAL_TIMESTAMP_GET_FLAG.
+ (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp()
+ function.
+
+ *** Tamper configuration ***
+ ============================
+ [..]
+ (+) Enable the RTC Tamper and configure the Tamper filter count, trigger Edge
+ or Level according to the Tamper filter (if equal to 0 Edge else Level)
+ value, sampling frequency, NoErase, MaskFlag, precharge or discharge and
+ Pull-UP using the HAL_RTCEx_SetTamper() function. You can configure RTC Tamper
+ with interrupt mode using HAL_RTCEx_SetTamper_IT() function.
+ (+) The default configuration of the Tamper erases the backup registers. To avoid
+ erase, enable the NoErase field on the RTC_TAMPCR register.
+
+ *** Backup Data Registers configuration ***
+ ===========================================
+ [..]
+ (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite()
+ function.
+ (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead()
+ function.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RTCEx RTCEx
+ * @brief RTC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#if defined(RTC_TAMPER1_SUPPORT) && defined(RTC_TAMPER3_SUPPORT)
+#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\
+ (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\
+ (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\
+ (uint32_t)RTC_TAMPCR_TAMP1IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\
+ (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF |\
+ (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP3MF)
+#elif defined(RTC_TAMPER1_SUPPORT)
+#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\
+ (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\
+ (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\
+ (uint32_t)RTC_TAMPCR_TAMP1IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\
+ (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF)
+#elif defined(RTC_TAMPER3_SUPPORT)
+#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\
+ (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\
+ (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\
+ (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF |\
+ (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP3MF)
+#else
+#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\
+ (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\
+ (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\
+ (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF)
+#endif /* RTC_TAMPER1_SUPPORT && RTC_TAMPER3_SUPPORT */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions
+ * @{
+ */
+
+
+/** @defgroup RTCEx_Exported_Functions_Group1 RTC TimeStamp and Tamper functions
+ * @brief RTC TimeStamp and Tamper functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC TimeStamp and Tamper functions #####
+ ===============================================================================
+
+ [..] This section provide functions allowing to configure TimeStamp feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set TimeStamp.
+ * @note This API must be called before enabling the TimeStamp feature.
+ * @param hrtc: RTC handle
+ * @param TimeStampEdge: Specifies the pin edge on which the TimeStamp is
+ * activated.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the
+ * rising edge of the related pin.
+ * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the
+ * falling edge of the related pin.
+ * @param RTC_TimeStampPin: specifies the RTC TimeStamp Pin.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin.
+ * The RTC TimeStamp Pin is per default PC13, but for reasons of
+ * compatibility, this parameter is required.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge));
+ assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ tmpreg|= TimeStampEdge;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Time Stamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ __HAL_RTC_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set TimeStamp with Interrupt.
+ * @param hrtc: RTC handle
+ * @note This API must be called before enabling the TimeStamp feature.
+ * @param TimeStampEdge: Specifies the pin edge on which the TimeStamp is
+ * activated.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the
+ * rising edge of the related pin.
+ * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the
+ * falling edge of the related pin.
+ * @param RTC_TimeStampPin: Specifies the RTC TimeStamp Pin.
+ * This parameter can be one of the following values:
+ * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin.
+ * The RTC TimeStamp Pin is per default PC13, but for reasons of
+ * compatibility, this parameter is required.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge));
+ assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ tmpreg |= TimeStampEdge;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the Time Stamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ __HAL_RTC_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable IT timestamp */
+ __HAL_RTC_TIMESTAMP_ENABLE_IT(hrtc,RTC_IT_TS);
+
+ /* RTC timestamp Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate TimeStamp.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tmpreg = 0;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_TIMESTAMP_DISABLE_IT(hrtc, RTC_IT_TS);
+
+ /* Get the RTC_CR register and clear the bits to be configured */
+ tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE));
+
+ /* Configure the Time Stamp TSEDGE and Enable bits */
+ hrtc->Instance->CR = (uint32_t)tmpreg;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Internal TimeStamp.
+ * @note This API must be called before enabling the internal TimeStamp feature.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the internal Time Stamp Enable bits */
+ __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate Internal TimeStamp.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the internal Time Stamp Enable bits */
+ __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the RTC TimeStamp value.
+ * @param hrtc: RTC handle
+ * @param sTimeStamp: Pointer to Time structure
+ * @param sTimeStampDate: Pointer to Date structure
+ * @param Format: specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef* sTimeStamp, RTC_DateTypeDef* sTimeStampDate, uint32_t Format)
+{
+ uint32_t tmptime = 0, tmpdate = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(Format));
+
+ /* Get the TimeStamp time and date registers values */
+ tmptime = (uint32_t)(hrtc->Instance->TSTR & RTC_TR_RESERVED_MASK);
+ tmpdate = (uint32_t)(hrtc->Instance->TSDR & RTC_DR_RESERVED_MASK);
+
+ /* Fill the Time structure fields with the read parameters */
+ sTimeStamp->Hours = (uint8_t)((tmptime & (RTC_TR_HT | RTC_TR_HU)) >> 16);
+ sTimeStamp->Minutes = (uint8_t)((tmptime & (RTC_TR_MNT | RTC_TR_MNU)) >> 8);
+ sTimeStamp->Seconds = (uint8_t)(tmptime & (RTC_TR_ST | RTC_TR_SU));
+ sTimeStamp->TimeFormat = (uint8_t)((tmptime & (RTC_TR_PM)) >> 16);
+ sTimeStamp->SubSeconds = (uint32_t) hrtc->Instance->TSSSR;
+
+ /* Fill the Date structure fields with the read parameters */
+ sTimeStampDate->Year = 0;
+ sTimeStampDate->Month = (uint8_t)((tmpdate & (RTC_DR_MT | RTC_DR_MU)) >> 8);
+ sTimeStampDate->Date = (uint8_t)(tmpdate & (RTC_DR_DT | RTC_DR_DU));
+ sTimeStampDate->WeekDay = (uint8_t)((tmpdate & (RTC_DR_WDU)) >> 13);
+
+ /* Check the input parameters format */
+ if(Format == RTC_FORMAT_BIN)
+ {
+ /* Convert the TimeStamp structure parameters to Binary format */
+ sTimeStamp->Hours = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Hours);
+ sTimeStamp->Minutes = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Minutes);
+ sTimeStamp->Seconds = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Seconds);
+
+ /* Convert the DateTimeStamp structure parameters to Binary format */
+ sTimeStampDate->Month = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Month);
+ sTimeStampDate->Date = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Date);
+ sTimeStampDate->WeekDay = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->WeekDay);
+ }
+
+ /* Clear the TIMESTAMP Flags */
+ __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_ITSF);
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Tamper.
+ * @note By calling this API we disable the tamper interrupt for all tampers.
+ * @param hrtc: RTC handle
+ * @param sTamper: Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Configure the tamper trigger */
+ if(sTamper->Trigger != RTC_TAMPERTRIGGER_RISINGEDGE)
+ {
+ sTamper->Trigger = (uint32_t)(sTamper->Tamper << 1);
+ }
+
+ if(sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+ sTamper->NoErase = 0;
+#if defined(RTC_TAMPER1_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE;
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE;
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE;
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ sTamper->MaskFlag = 0;
+#if defined(RTC_TAMPER1_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF;
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF;
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF;
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ tmpreg = ((uint32_t)sTamper->Tamper | (uint32_t)sTamper->Trigger | (uint32_t)sTamper->NoErase |\
+ (uint32_t)sTamper->MaskFlag | (uint32_t)sTamper->Filter | (uint32_t)sTamper->SamplingFrequency |\
+ (uint32_t)sTamper->PrechargeDuration | (uint32_t)sTamper->TamperPullUp | sTamper->TimeStampOnTamperDetection);
+
+ hrtc->Instance->TAMPCR &= (uint32_t)~((uint32_t)sTamper->Tamper | (uint32_t)(sTamper->Tamper << 1) | RTC_TAMPCR_MASK);
+
+ hrtc->Instance->TAMPCR |= tmpreg;
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Tamper with interrupt.
+ * @note By calling this API we force the tamper interrupt for all tampers.
+ * @param hrtc: RTC handle
+ * @param sTamper: Pointer to RTC Tamper.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER(sTamper->Tamper));
+ assert_param(IS_RTC_TAMPER_INTERRUPT(sTamper->Interrupt));
+ assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
+ assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase));
+ assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag));
+ assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter));
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency));
+ assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration));
+ assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp));
+ assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Configure the tamper trigger */
+ if(sTamper->Trigger != RTC_TAMPERTRIGGER_RISINGEDGE)
+ {
+ sTamper->Trigger = (uint32_t)(sTamper->Tamper << 1);
+ }
+
+ if(sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE)
+ {
+ sTamper->NoErase = 0;
+#if defined(RTC_TAMPER1_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE;
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE;
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE;
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ sTamper->MaskFlag = 0;
+#if defined(RTC_TAMPER1_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF;
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF;
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF;
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+ }
+
+ tmpreg = ((uint32_t)sTamper->Tamper | (uint32_t)sTamper->Interrupt | (uint32_t)sTamper->Trigger | (uint32_t)sTamper->NoErase |\
+ (uint32_t)sTamper->MaskFlag | (uint32_t)sTamper->Filter | (uint32_t)sTamper->SamplingFrequency |\
+ (uint32_t)sTamper->PrechargeDuration | (uint32_t)sTamper->TamperPullUp | sTamper->TimeStampOnTamperDetection);
+
+ hrtc->Instance->TAMPCR &= (uint32_t)~((uint32_t)sTamper->Tamper | (uint32_t)(sTamper->Tamper << 1) | RTC_TAMPCR_MASK);
+
+ hrtc->Instance->TAMPCR |= tmpreg;
+
+ /* RTC Tamper Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE();
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate Tamper.
+ * @param hrtc: RTC handle
+ * @param Tamper: Selected tamper pin.
+ * This parameter can be any combination of RTC_TAMPER_1, RTC_TAMPER_2 and RTC_TAMPER_3.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper)
+{
+ assert_param(IS_RTC_TAMPER(Tamper));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the selected Tamper pin */
+ hrtc->Instance->TAMPCR &= ((uint32_t)~Tamper);
+
+#if defined(RTC_TAMPER1_SUPPORT)
+ if ((Tamper & RTC_TAMPER_1) != 0)
+ {
+ /* Disable the Tamper1 interrupt */
+ hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1));
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+ if ((Tamper & RTC_TAMPER_2) != 0)
+ {
+ /* Disable the Tamper2 interrupt */
+ hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2));
+ }
+#if defined(RTC_TAMPER3_SUPPORT)
+ if ((Tamper & RTC_TAMPER_3) != 0)
+ {
+ /* Disable the Tamper3 interrupt */
+ hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3));
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle TimeStamp interrupt request.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Get the TimeStamp interrupt source enable status */
+ if(__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != RESET)
+ {
+ /* Get the pending status of the TIMESTAMP Interrupt */
+ if(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != RESET)
+ {
+ /* TIMESTAMP callback */
+ HAL_RTCEx_TimeStampEventCallback(hrtc);
+
+ /* Clear the TIMESTAMP interrupt pending bit */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+ }
+ }
+
+#if defined(RTC_TAMPER1_SUPPORT)
+ /* Get the Tamper1 interrupts source enable status */
+ if(__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != RESET)
+ {
+ /* Get the pending status of the Tamper1 Interrupt */
+ if(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != RESET)
+ {
+ /* Tamper1 callback */
+ HAL_RTCEx_Tamper1EventCallback(hrtc);
+
+ /* Clear the Tamper1 interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
+ }
+ }
+#endif /* RTC_TAMPER1_SUPPORT */
+
+ /* Get the Tamper2 interrupts source enable status */
+ if(__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != RESET)
+ {
+ /* Get the pending status of the Tamper2 Interrupt */
+ if(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != RESET)
+ {
+ /* Tamper2 callback */
+ HAL_RTCEx_Tamper2EventCallback(hrtc);
+
+ /* Clear the Tamper2 interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+ }
+ }
+
+#if defined(RTC_TAMPER3_SUPPORT)
+ /* Get the Tamper3 interrupts source enable status */
+ if(__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != RESET)
+ {
+ /* Get the pending status of the Tamper3 Interrupt */
+ if(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != RESET)
+ {
+ /* Tamper3 callback */
+ HAL_RTCEx_Tamper3EventCallback(hrtc);
+
+ /* Clear the Tamper3 interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+ }
+ }
+#endif /* RTC_TAMPER3_SUPPORT */
+
+ /* Clear the EXTI's Flag for RTC TimeStamp and Tamper */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief TimeStamp callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_TimeStampEventCallback could be implemented in the user file
+ */
+}
+
+#if defined(RTC_TAMPER1_SUPPORT)
+/**
+ * @brief Tamper 1 callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER1_SUPPORT */
+
+/**
+ * @brief Tamper 2 callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file
+ */
+}
+
+#if defined(RTC_TAMPER3_SUPPORT)
+/**
+ * @brief Tamper 3 callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper3EventCallback could be implemented in the user file
+ */
+}
+#endif /* RTC_TAMPER3_SUPPORT */
+
+/**
+ * @brief Handle TimeStamp polling request.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == RESET)
+ {
+ if(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSOVF) != RESET)
+ {
+ /* Clear the TIMESTAMP OverRun Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF);
+
+ /* Change TIMESTAMP state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+#if defined(RTC_TAMPER1_SUPPORT)
+/**
+ * @brief Handle Tamper 1 Polling.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F)== RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER1_SUPPORT */
+
+/**
+ * @brief Handle Tamper 2 Polling.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+#if defined(RTC_TAMPER3_SUPPORT)
+/**
+ * @brief Handle Tamper 3 Polling.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Get the status of the Interrupt */
+ while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Tamper Flag */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+#endif /* RTC_TAMPER3_SUPPORT */
+
+/**
+ * @}
+ */
+
+/** @defgroup RTCEx_Exported_Functions_Group2 RTC Wake-up functions
+ * @brief RTC Wake-up functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Wake-up functions #####
+ ===============================================================================
+
+ [..] This section provide functions allowing to configure Wake-up feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set wake up timer.
+ * @param hrtc: RTC handle
+ * @param WakeUpCounter: Wake up counter
+ * @param WakeUpClock: Wake up clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock));
+ assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /*Check RTC WUTWF flag is reset only when wake up timer enabled*/
+ if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET)
+ {
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == SET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear the Wakeup Timer clock source bits in CR register */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL;
+
+ /* Configure the clock source */
+ hrtc->Instance->CR |= (uint32_t)WakeUpClock;
+
+ /* Configure the Wakeup Timer counter */
+ hrtc->Instance->WUTR = (uint32_t)WakeUpCounter;
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set wake up timer with interrupt.
+ * @param hrtc: RTC handle
+ * @param WakeUpCounter: Wake up counter
+ * @param WakeUpClock: Wake up clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock));
+ assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /*Check RTC WUTWF flag is reset only when wake up timer enabled*/
+ if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET)
+ {
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == SET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait till RTC WUTWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure the Wakeup Timer counter */
+ hrtc->Instance->WUTR = (uint32_t)WakeUpCounter;
+
+ /* Clear the Wakeup Timer clock source bits in CR register */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL;
+
+ /* Configure the clock source */
+ hrtc->Instance->CR |= (uint32_t)WakeUpClock;
+
+ /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
+
+ __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
+
+ /* Configure the Interrupt in the RTC_CR register */
+ __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc,RTC_IT_WUT);
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate wake up timer counter.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+uint32_t HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tickstart = 0;
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Disable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* In case of interrupt mode is used, the interrupt source must disabled */
+ __HAL_RTC_WAKEUPTIMER_DISABLE_IT(hrtc,RTC_IT_WUT);
+
+ tickstart = HAL_GetTick();
+ /* Wait till RTC WUTWF flag is set and if Time out is reached exit */
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get wake up timer counter.
+ * @param hrtc: RTC handle
+ * @retval Counter value
+ */
+uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ /* Get the counter value */
+ return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT));
+}
+
+/**
+ * @brief Handle Wake Up Timer interrupt request.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ /* Get the pending status of the WAKEUPTIMER Interrupt */
+ if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) != RESET)
+ {
+ /* WAKEUPTIMER callback */
+ HAL_RTCEx_WakeUpTimerEventCallback(hrtc);
+
+ /* Clear the WAKEUPTIMER interrupt pending bit */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+ }
+
+
+ /* Clear the EXTI's line Flag for RTC WakeUpTimer */
+ __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+}
+
+/**
+ * @brief Wake Up Timer callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handle Wake Up Timer Polling.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the WAKEUPTIMER Flag */
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Write a data in a specified RTC Backup data register
+ (+) Read a data in a specified RTC Backup data register
+ (+) Set the Coarse calibration parameters.
+ (+) Deactivate the Coarse calibration parameters
+ (+) Set the Smooth calibration parameters.
+ (+) Configure the Synchronization Shift Control Settings.
+ (+) Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ (+) Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ (+) Enable the RTC reference clock detection.
+ (+) Disable the RTC reference clock detection.
+ (+) Enable the Bypass Shadow feature.
+ (+) Disable the Bypass Shadow feature.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Write a data in a specified RTC Backup data register.
+ * @param hrtc: RTC handle
+ * @param BackupRegister: RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to
+ * specify the register.
+ * @param Data: Data to be written in the specified RTC Backup data register.
+ * @retval None
+ */
+void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
+{
+ uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_BKP(BackupRegister));
+
+ tmp = (uint32_t)&(hrtc->Instance->BKP0R);
+ tmp += (BackupRegister * 4);
+
+ /* Write the specified register */
+ *(__IO uint32_t *)tmp = (uint32_t)Data;
+}
+
+/**
+ * @brief Read data from the specified RTC Backup data Register.
+ * @param hrtc: RTC handle
+ * @param BackupRegister: RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to
+ * specify the register.
+ * @retval Read value
+ */
+uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
+{
+ uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_BKP(BackupRegister));
+
+ tmp = (uint32_t)&(hrtc->Instance->BKP0R);
+ tmp += (BackupRegister * 4);
+
+ /* Read the specified register */
+ return (*(__IO uint32_t *)tmp);
+}
+
+/**
+ * @brief Set the Smooth calibration parameters.
+ * @param hrtc: RTC handle
+ * @param SmoothCalibPeriod: Select the Smooth Calibration Period.
+ * This parameter can be can be one of the following values :
+ * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s.
+ * @param SmoothCalibPlusPulses: Select to Set or reset the CALP bit.
+ * This parameter can be one of the following values:
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulse every 2*11 pulses.
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added.
+ * @param SmoothCalibMinusPulsesValue: Select the value of CALM[8:0] bits.
+ * This parameter can be one any value from 0 to 0x000001FF.
+ * @note To deactivate the smooth calibration, the field SmoothCalibPlusPulses
+ * must be equal to SMOOTHCALIB_PLUSPULSES_RESET and the field
+ * SmoothCalibMinusPulsesValue must be equal to 0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef* hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(SmoothCalibPeriod));
+ assert_param(IS_RTC_SMOOTH_CALIB_PLUS(SmoothCalibPlusPulses));
+ assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmoothCalibMinusPulsesValue));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* check if a calibration is pending*/
+ if((hrtc->Instance->ISR & RTC_ISR_RECALPF) != RESET)
+ {
+ tickstart = HAL_GetTick();
+
+ /* check if a calibration is pending*/
+ while((hrtc->Instance->ISR & RTC_ISR_RECALPF) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Configure the Smooth calibration settings */
+ hrtc->Instance->CALR = (uint32_t)((uint32_t)SmoothCalibPeriod | (uint32_t)SmoothCalibPlusPulses | (uint32_t)SmoothCalibMinusPulsesValue);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the Synchronization Shift Control Settings.
+ * @note When REFCKON is set, firmware must not write to Shift control register.
+ * @param hrtc: RTC handle
+ * @param ShiftAdd1S: Select to add or not 1 second to the time calendar.
+ * This parameter can be one of the following values :
+ * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar.
+ * @arg RTC_SHIFTADD1S_RESET: No effect.
+ * @param ShiftSubFS: Select the number of Second Fractions to substitute.
+ * This parameter can be one any value from 0 to 0x7FFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef* hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SHIFT_ADD1S(ShiftAdd1S));
+ assert_param(IS_RTC_SHIFT_SUBFS(ShiftSubFS));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ tickstart = HAL_GetTick();
+
+ /* Wait until the shift is completed*/
+ while((hrtc->Instance->ISR & RTC_ISR_SHPF) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check if the reference clock detection is disabled */
+ if((hrtc->Instance->CR & RTC_CR_REFCKON) == RESET)
+ {
+ /* Configure the Shift settings */
+ hrtc->Instance->SHIFTR = (uint32_t)(uint32_t)(ShiftSubFS) | (uint32_t)(ShiftAdd1S);
+
+ /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET)
+ {
+ if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc: RTC handle
+ * @param CalibOutput : Select the Calibration output Selection .
+ * This parameter can be one of the following values:
+ * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz.
+ * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef* hrtc, uint32_t CalibOutput)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Clear flags before config */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL;
+
+ /* Configure the RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)CalibOutput;
+
+ __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the RTC reference clock detection.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state*/
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ __HAL_RTC_CLOCKREF_DETECTION_ENABLE(hrtc);
+
+ /* Exit Initialization mode */
+ hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the RTC reference clock detection.
+ * @param hrtc: RTC handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set Initialization mode */
+ if(RTC_EnterInitMode(hrtc) != HAL_OK)
+ {
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Set RTC state*/
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ __HAL_RTC_CLOCKREF_DETECTION_DISABLE(hrtc);
+
+ /* Exit Initialization mode */
+ hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
+ }
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the Bypass Shadow feature.
+ * @param hrtc: RTC handle
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set the BYPSHAD bit */
+ hrtc->Instance->CR |= (uint8_t)RTC_CR_BYPSHAD;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Bypass Shadow feature.
+ * @param hrtc: RTC handle
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Reset the BYPSHAD bit */
+ hrtc->Instance->CR &= ((uint8_t)~RTC_CR_BYPSHAD);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTCEx_Exported_Functions_Group4 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) RTC Alarm B callback
+ (+) RTC Poll for Alarm B request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Alarm B callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hrtc);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_RTCEx_AlarmBEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Handle Alarm B Polling request.
+ * @param hrtc: RTC handle
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear the Alarm Flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RTC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_sd.c b/stmhal/hal/l4/src/stm32l4xx_hal_sd.c
new file mode 100644
index 000000000..6956fb925
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_sd.c
@@ -0,0 +1,3412 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_sd.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief SD card HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Secure Digital (SD) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver implements a high level communication layer for read and write from/to
+ this memory. The needed STM32 hardware resources (SDMMC1 and GPIO) are performed by
+ the user in HAL_SD_MspInit() function (MSP layer).
+ Basically, the MSP layer configuration should be the same as we provide in the
+ examples.
+ You can easily tailor this configuration according to hardware resources.
+
+ [..]
+ This driver is a generic layered driver for SDMMC memories which uses the HAL
+ SDMMC driver functions to interface with SD and uSD cards devices.
+ It is used as follows:
+
+ (#)Initialize the SDMMC1 low level resources by implementing the HAL_SD_MspInit() API:
+ (##) Call the function HAL_RCCEx_PeriphCLKConfig with RCC_PERIPHCLK_SDMMC1 for
+ PeriphClockSelection and select SDMMC1 clock source (MSI, main PLL or PLLSAI1)
+ (##) Enable the SDMMC1 interface clock using __HAL_RCC_SDMMC1_CLK_ENABLE();
+ (##) SDMMC pins configuration for SD card
+ (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
+ (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
+ and according to your pin assignment;
+ (##) DMA Configuration if you need to use DMA process (HAL_SD_ReadBlocks_DMA()
+ and HAL_SD_WriteBlocks_DMA() APIs).
+ (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
+ (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
+ (##) NVIC configuration if you need to use interrupt process when using DMA transfer.
+ (+++) Configure the SDMMC and DMA interrupt priorities using functions
+ HAL_NVIC_SetPriority(); DMA priority is superior to SDMMC's priority
+ (+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ()
+ (+++) SDMMC interrupts are managed using the macros __HAL_SD_SDMMC_ENABLE_IT()
+ and __HAL_SD_SDMMC_DISABLE_IT() inside the communication process.
+ (+++) SDMMC interrupts pending bits are managed using the macros __HAL_SD_SDMMC_GET_IT()
+ and __HAL_SD_SDMMC_CLEAR_IT()
+ (#) At this stage, you can perform SD read/write/erase operations after SD card initialization
+
+
+ *** SD Card Initialization and configuration ***
+ ================================================
+ [..]
+ To initialize the SD Card, use the HAL_SD_Init() function. It Initializes
+ the SD Card and put it into StandBy State (Ready for data transfer).
+ This function provide the following operations:
+
+ (#) Apply the SD Card initialization process at 400KHz and check the SD Card
+ type (Standard Capacity or High Capacity). You can change or adapt this
+ frequency by adjusting the "ClockDiv" field.
+ The SD Card frequency (SDMMC_CK) is computed as follows:
+ (++)
+
+ SDMMC_CK = SDMMCCLK / (ClockDiv + 2)
+
+ -@@- In initialization mode and according to the SD Card standard,
+ make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
+
+ (#) Get the SD CID and CSD data. All these information are managed by the SDCardInfo
+ structure. This structure provide also ready computed SD Card capacity
+ and Block size.
+
+ -@- These information are stored in SD handle structure in case of future use.
+
+ (#) Configure the SD Card Data transfer frequency. By Default, the card transfer
+ frequency is set to 24MHz. You can change or adapt this frequency by adjusting
+ the "ClockDiv" field.
+ In transfer mode and according to the SD Card standard, make sure that the
+ SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
+ To be able to use a frequency higher than 24MHz, you should use the SDMMC
+ peripheral in bypass mode. Refer to the corresponding reference manual
+ for more details.
+
+ (#) Select the corresponding SD Card according to the address read with the step 2.
+
+ (#) Configure the SD Card in wide bus mode: 4-bits data.
+
+ *** SD Card Read operation ***
+ ==============================
+ [..]
+ (+) You can read from SD card in polling mode by using function HAL_SD_ReadBlocks().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+
+ (+) You can read from SD card in DMA mode by using function HAL_SD_ReadBlocks_DMA().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to call the function HAL_SD_CheckReadOperation(), to insure
+ that the read transfer is done correctly in both DMA and SD sides.
+
+ *** SD Card Write operation ***
+ ===============================
+ [..]
+ (+) You can write to SD card in polling mode by using function HAL_SD_WriteBlocks().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 bytes).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+
+ (+) You can write to SD card in DMA mode by using function HAL_SD_WriteBlocks_DMA().
+ This function support only 512-bytes block length (the block size should be
+ chosen as 512 byte).
+ You can choose either one block read operation or multiple block read operation
+ by adjusting the "NumberOfBlocks" parameter.
+ After this, you have to call the function HAL_SD_CheckWriteOperation(), to insure
+ that the write transfer is done correctly in both DMA and SD sides.
+
+ *** SD card status ***
+ ======================
+ [..]
+ (+) At any time, you can check the SD Card status and get the SD card state
+ by using the HAL_SD_GetStatus() function. This function checks first if the
+ SD card is still connected and then get the internal SD Card transfer state.
+ (+) You can also get the SD card SD Status register by using the HAL_SD_SendSDStatus()
+ function.
+
+ *** SD HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in SD HAL driver.
+
+ (+) __HAL_SD_SDMMC_ENABLE : Enable the SD device
+ (+) __HAL_SD_SDMMC_DISABLE : Disable the SD device
+ (+) __HAL_SD_SDMMC_DMA_ENABLE: Enable the SDMMC DMA transfer
+ (+) __HAL_SD_SDMMC_DMA_DISABLE: Disable the SDMMC DMA transfer
+ (+) __HAL_SD_SDMMC_ENABLE_IT: Enable the SD device interrupt
+ (+) __HAL_SD_SDMMC_DISABLE_IT: Disable the SD device interrupt
+ (+) __HAL_SD_SDMMC_GET_FLAG:Check whether the specified SD flag is set or not
+ (+) __HAL_SD_SDMMC_CLEAR_FLAG: Clear the SD's pending flags
+ [..]
+ (@) You can refer to the SD HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup SD
+ * @{
+ */
+
+#ifdef HAL_SD_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup SD_Private_Defines
+ * @{
+ */
+/**
+ * @brief SDMMC Data block size
+ */
+#define DATA_BLOCK_SIZE ((uint32_t)(9 << 4))
+/**
+ * @brief SDMMC Static flags, Timeout, FIFO Address
+ */
+#define SDMMC_STATIC_FLAGS ((uint32_t)(SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_CTIMEOUT |\
+ SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_RXOVERR |\
+ SDMMC_FLAG_CMDREND | SDMMC_FLAG_CMDSENT | SDMMC_FLAG_DATAEND |\
+ SDMMC_FLAG_DBCKEND))
+
+#define SDMMC_CMD0TIMEOUT ((uint32_t)0x00010000)
+
+/**
+ * @brief Mask for errors Card Status R1 (OCR Register)
+ */
+#define SD_OCR_ADDR_OUT_OF_RANGE ((uint32_t)0x80000000)
+#define SD_OCR_ADDR_MISALIGNED ((uint32_t)0x40000000)
+#define SD_OCR_BLOCK_LEN_ERR ((uint32_t)0x20000000)
+#define SD_OCR_ERASE_SEQ_ERR ((uint32_t)0x10000000)
+#define SD_OCR_BAD_ERASE_PARAM ((uint32_t)0x08000000)
+#define SD_OCR_WRITE_PROT_VIOLATION ((uint32_t)0x04000000)
+#define SD_OCR_LOCK_UNLOCK_FAILED ((uint32_t)0x01000000)
+#define SD_OCR_COM_CRC_FAILED ((uint32_t)0x00800000)
+#define SD_OCR_ILLEGAL_CMD ((uint32_t)0x00400000)
+#define SD_OCR_CARD_ECC_FAILED ((uint32_t)0x00200000)
+#define SD_OCR_CC_ERROR ((uint32_t)0x00100000)
+#define SD_OCR_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00080000)
+#define SD_OCR_STREAM_READ_UNDERRUN ((uint32_t)0x00040000)
+#define SD_OCR_STREAM_WRITE_OVERRUN ((uint32_t)0x00020000)
+#define SD_OCR_CID_CSD_OVERWRITE ((uint32_t)0x00010000)
+#define SD_OCR_WP_ERASE_SKIP ((uint32_t)0x00008000)
+#define SD_OCR_CARD_ECC_DISABLED ((uint32_t)0x00004000)
+#define SD_OCR_ERASE_RESET ((uint32_t)0x00002000)
+#define SD_OCR_AKE_SEQ_ERROR ((uint32_t)0x00000008)
+#define SD_OCR_ERRORBITS ((uint32_t)0xFDFFE008)
+
+/**
+ * @brief Masks for R6 Response
+ */
+#define SD_R6_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00002000)
+#define SD_R6_ILLEGAL_CMD ((uint32_t)0x00004000)
+#define SD_R6_COM_CRC_FAILED ((uint32_t)0x00008000)
+
+#define SD_VOLTAGE_WINDOW_SD ((uint32_t)0x80100000)
+#define SD_HIGH_CAPACITY ((uint32_t)0x40000000)
+#define SD_STD_CAPACITY ((uint32_t)0x00000000)
+#define SD_CHECK_PATTERN ((uint32_t)0x000001AA)
+
+#define SD_MAX_VOLT_TRIAL ((uint32_t)0x0000FFFF)
+#define SD_ALLZERO ((uint32_t)0x00000000)
+
+#define SD_WIDE_BUS_SUPPORT ((uint32_t)0x00040000)
+#define SD_SINGLE_BUS_SUPPORT ((uint32_t)0x00010000)
+#define SD_CARD_LOCKED ((uint32_t)0x02000000)
+
+#define SD_DATATIMEOUT ((uint32_t)0xFFFFFFFF)
+#define SD_0TO7BITS ((uint32_t)0x000000FF)
+#define SD_8TO15BITS ((uint32_t)0x0000FF00)
+#define SD_16TO23BITS ((uint32_t)0x00FF0000)
+#define SD_24TO31BITS ((uint32_t)0xFF000000)
+#define SD_MAX_DATA_LENGTH ((uint32_t)0x01FFFFFF)
+
+#define SD_HALFFIFO ((uint32_t)0x00000008)
+#define SD_HALFFIFOBYTES ((uint32_t)0x00000020)
+
+/**
+ * @brief Command Class Supported
+ */
+#define SD_CCCC_LOCK_UNLOCK ((uint32_t)0x00000080)
+#define SD_CCCC_WRITE_PROT ((uint32_t)0x00000040)
+#define SD_CCCC_ERASE ((uint32_t)0x00000020)
+
+/**
+ * @brief Following commands are SD Card Specific commands.
+ * SDMMC_APP_CMD should be sent before sending these commands.
+ */
+#define SD_SDMMC_SEND_IF_COND ((uint32_t)SD_CMD_HS_SEND_EXT_CSD)
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup SD_Private_Functions_Prototypes
+ * @{
+ */
+static HAL_SD_ErrorTypedef SD_Initialize_Cards(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_Select_Deselect(SD_HandleTypeDef *hsd, uint64_t addr);
+static HAL_SD_ErrorTypedef SD_PowerON(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_PowerOFF(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus);
+static HAL_SD_CardStateTypedef SD_GetState(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_IsCardProgramming(SD_HandleTypeDef *hsd, uint8_t *pStatus);
+static HAL_SD_ErrorTypedef SD_CmdError(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_CmdResp1Error(SD_HandleTypeDef *hsd, uint8_t SD_CMD);
+static HAL_SD_ErrorTypedef SD_CmdResp7Error(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_CmdResp3Error(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_CmdResp2Error(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_CmdResp6Error(SD_HandleTypeDef *hsd, uint8_t SD_CMD, uint16_t *pRCA);
+static HAL_SD_ErrorTypedef SD_WideBus_Enable(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_WideBus_Disable(SD_HandleTypeDef *hsd);
+static HAL_SD_ErrorTypedef SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR);
+static void SD_DMA_RxCplt(DMA_HandleTypeDef *hdma);
+static void SD_DMA_RxError(DMA_HandleTypeDef *hdma);
+static void SD_DMA_TxCplt(DMA_HandleTypeDef *hdma);
+static void SD_DMA_TxError(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SD_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup SD_Exported_Functions_Group1
+ * @brief Initialization and de-initialization functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to initialize/de-initialize the SD
+ card device to be ready for use.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the SD card according to the specified parameters in the
+ SD_HandleTypeDef and initialize the associated handle.
+ * @param hsd: SD handle
+ * @param SDCardInfo: HAL_SD_CardInfoTypedef structure for SD card information
+ * @retval HAL SD error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_Init(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *SDCardInfo)
+{
+ __IO HAL_SD_ErrorTypedef errorstate = SD_OK;
+ SD_InitTypeDef tmpinit;
+
+ /* Initialize the low level hardware (MSP) */
+ HAL_SD_MspInit(hsd);
+
+ /* Default SDMMC peripheral configuration for SD card initialization */
+ tmpinit.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
+ tmpinit.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
+ tmpinit.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
+ tmpinit.BusWide = SDMMC_BUS_WIDE_1B;
+ tmpinit.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
+ tmpinit.ClockDiv = SDMMC_INIT_CLK_DIV;
+
+ /* Initialize SDMMC peripheral interface with default configuration */
+ SDMMC_Init(hsd->Instance, tmpinit);
+
+ /* Identify card operating voltage */
+ errorstate = SD_PowerON(hsd);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Initialize the present SDMMC card(s) and put them in idle state */
+ errorstate = SD_Initialize_Cards(hsd);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Read CSD/CID MSD registers */
+ errorstate = HAL_SD_Get_CardInfo(hsd, SDCardInfo);
+
+ if (errorstate == SD_OK)
+ {
+ /* Select the Card */
+ errorstate = SD_Select_Deselect(hsd, (uint32_t)(((uint32_t)SDCardInfo->RCA) << 16));
+ }
+
+ /* Configure SDMMC peripheral interface */
+ SDMMC_Init(hsd->Instance, hsd->Init);
+
+ return errorstate;
+}
+
+/**
+ * @brief De-Initializes the SD card.
+ * @param hsd: SD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
+{
+
+ /* Set SD power state to off */
+ SD_PowerOFF(hsd);
+
+ /* De-Initialize the MSP layer */
+ HAL_SD_MspDeInit(hsd);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initializes the SD MSP.
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief De-Initialize SD MSP.
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup SD_Exported_Functions_Group2
+ * @brief Data transfer functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the data
+ transfer from/to SD card.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed by polling mode.
+ * @param hsd: SD handle
+ * @param pReadBuffer: pointer to the buffer that will contain the received data
+ * @param ReadAddr: Address from where data is to be read
+ * @param BlockSize: SD card Data block size
+ * @note BlockSize must be 512 bytes.
+ * @param NumberOfBlocks: Number of SD blocks to read
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint32_t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t count = 0, *tempbuff = (uint32_t *)pReadBuffer;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0;
+
+ if (hsd->CardType == HIGH_CAPACITY_SD_CARD)
+ {
+ BlockSize = 512;
+ ReadAddr /= 512;
+ }
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinitstructure.Argument = (uint32_t) BlockSize;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = NumberOfBlocks * BlockSize;
+ sdmmc_datainitstructure.DataBlockSize = DATA_BLOCK_SIZE;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ if(NumberOfBlocks > 1)
+ {
+ /* Send CMD18 READ_MULT_BLOCK with argument data address */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_MULT_BLOCK;
+ }
+ else
+ {
+ /* Send CMD17 READ_SINGLE_BLOCK */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_SINGLE_BLOCK;
+ }
+
+ sdmmc_cmdinitstructure.Argument = (uint32_t)ReadAddr;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Read block(s) in polling mode */
+ if(NumberOfBlocks > 1)
+ {
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_READ_MULT_BLOCK);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Poll on SDMMC flags */
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for (count = 0; count < 8; count++)
+ {
+ *(tempbuff + count) = SDMMC_ReadFIFO(hsd->Instance);
+ }
+
+ tempbuff += 8;
+ }
+ }
+ }
+ else
+ {
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_READ_SINGLE_BLOCK);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* In case of single block transfer, no need of stop transfer at all */
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
+ {
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ /* Read data from SDMMC Rx FIFO */
+ for (count = 0; count < 8; count++)
+ {
+ *(tempbuff + count) = SDMMC_ReadFIFO(hsd->Instance);
+ }
+
+ tempbuff += 8;
+ }
+ }
+ }
+
+ /* Send stop transmission command in case of multiblock read */
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1))
+ {
+ if ((hsd->CardType == STD_CAPACITY_SD_CARD_V1_1) ||\
+ (hsd->CardType == STD_CAPACITY_SD_CARD_V2_0) ||\
+ (hsd->CardType == HIGH_CAPACITY_SD_CARD))
+ {
+ /* Send stop transmission command */
+ errorstate = HAL_SD_StopTransfer(hsd);
+ }
+ }
+
+ /* Get error state */
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ errorstate = SD_DATA_TIMEOUT;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SD_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SD_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ count = SD_DATATIMEOUT;
+
+ /* Empty FIFO if there is still any data */
+ while ((__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL)) && (count > 0))
+ {
+ *tempbuff = SDMMC_ReadFIFO(hsd->Instance);
+ tempbuff++;
+ count--;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ return errorstate;
+}
+
+/**
+ * @brief Allows to write block(s) to a specified address in a card. The Data
+ * transfer is managed by polling mode.
+ * @param hsd: SD handle
+ * @param pWriteBuffer: pointer to the buffer that will contain the data to transmit
+ * @param WriteAddr: Address from where data is to be written
+ * @param BlockSize: SD card Data block size
+ * @note BlockSize must be 512 bytes.
+ * @param NumberOfBlocks: Number of SD blocks to write
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint32_t *pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t totalnumberofbytes = 0, bytestransferred = 0, count = 0, restwords = 0;
+ uint32_t *tempbuff = (uint32_t *)pWriteBuffer;
+ uint8_t cardstate = 0;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0;
+
+ if (hsd->CardType == HIGH_CAPACITY_SD_CARD)
+ {
+ BlockSize = 512;
+ WriteAddr /= 512;
+ }
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)BlockSize;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ if(NumberOfBlocks > 1)
+ {
+ /* Send CMD25 WRITE_MULT_BLOCK with argument data address */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_MULT_BLOCK;
+ }
+ else
+ {
+ /* Send CMD24 WRITE_SINGLE_BLOCK */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;
+ }
+
+ sdmmc_cmdinitstructure.Argument = (uint32_t)WriteAddr;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ if(NumberOfBlocks > 1)
+ {
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_WRITE_MULT_BLOCK);
+ }
+ else
+ {
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_WRITE_SINGLE_BLOCK);
+ }
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Set total number of bytes to write */
+ totalnumberofbytes = NumberOfBlocks * BlockSize;
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = NumberOfBlocks * BlockSize;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ /* Write block(s) in polling mode */
+ if(NumberOfBlocks > 1)
+ {
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
+ {
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE))
+ {
+ if ((totalnumberofbytes - bytestransferred) < 32)
+ {
+ restwords = ((totalnumberofbytes - bytestransferred) % 4 == 0) ? ((totalnumberofbytes - bytestransferred) / 4) : (( totalnumberofbytes - bytestransferred) / 4 + 1);
+
+ /* Write data to SDMMC Tx FIFO */
+ for (count = 0; count < restwords; count++)
+ {
+ SDMMC_WriteFIFO(hsd->Instance, tempbuff);
+ tempbuff++;
+ bytestransferred += 4;
+ }
+ }
+ else
+ {
+ /* Write data to SDMMC Tx FIFO */
+ for (count = 0; count < 8; count++)
+ {
+ SDMMC_WriteFIFO(hsd->Instance, (tempbuff + count));
+ }
+
+ tempbuff += 8;
+ bytestransferred += 32;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* In case of single data block transfer no need of stop command at all */
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
+ {
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE))
+ {
+ if ((totalnumberofbytes - bytestransferred) < 32)
+ {
+ restwords = ((totalnumberofbytes - bytestransferred) % 4 == 0) ? ((totalnumberofbytes - bytestransferred) / 4) : (( totalnumberofbytes - bytestransferred) / 4 + 1);
+
+ /* Write data to SDMMC Tx FIFO */
+ for (count = 0; count < restwords; count++)
+ {
+ SDMMC_WriteFIFO(hsd->Instance, tempbuff);
+ tempbuff++;
+ bytestransferred += 4;
+ }
+ }
+ else
+ {
+ /* Write data to SDMMC Tx FIFO */
+ for (count = 0; count < 8; count++)
+ {
+ SDMMC_WriteFIFO(hsd->Instance, (tempbuff + count));
+ }
+
+ tempbuff += 8;
+ bytestransferred += 32;
+ }
+ }
+ }
+ }
+
+ /* Send stop transmission command in case of multiblock write */
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1))
+ {
+ if ((hsd->CardType == STD_CAPACITY_SD_CARD_V1_1) || (hsd->CardType == STD_CAPACITY_SD_CARD_V2_0) ||\
+ (hsd->CardType == HIGH_CAPACITY_SD_CARD))
+ {
+ /* Send stop transmission command */
+ errorstate = HAL_SD_StopTransfer(hsd);
+ }
+ }
+
+ /* Get error state */
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ errorstate = SD_DATA_TIMEOUT;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SD_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_TXUNDERR);
+
+ errorstate = SD_TX_UNDERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ /* Wait till the card is in programming state */
+ errorstate = SD_IsCardProgramming(hsd, &cardstate);
+
+ while ((errorstate == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING)))
+ {
+ errorstate = SD_IsCardProgramming(hsd, &cardstate);
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Reads block(s) from a specified address in a card. The Data transfer
+ * is managed by DMA mode.
+ * @note This API should be followed by the function HAL_SD_CheckReadOperation()
+ * to check the completion of the read process
+ * @param hsd: SD handle
+ * @param pReadBuffer: Pointer to the buffer that will contain the received data
+ * @param ReadAddr: Address from where data is to be read
+ * @param BlockSize: SD card Data block size
+ * @note BlockSize must be 512 bytes.
+ * @param NumberOfBlocks: Number of blocks to read.
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0;
+
+ /* Initialize handle flags */
+ hsd->SdTransferCplt = 0;
+ hsd->DmaTransferCplt = 0;
+ hsd->SdTransferErr = SD_OK;
+
+ /* Initialize SD Read operation */
+ if(NumberOfBlocks > 1)
+ {
+ hsd->SdOperation = SD_READ_MULTIPLE_BLOCK;
+ }
+ else
+ {
+ hsd->SdOperation = SD_READ_SINGLE_BLOCK;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_SD_SDMMC_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL |\
+ SDMMC_IT_DTIMEOUT |\
+ SDMMC_IT_DATAEND |\
+ SDMMC_IT_RXOVERR));
+
+ /* Enable SDMMC DMA transfer */
+ __HAL_SD_SDMMC_DMA_ENABLE(hsd);
+
+ /* Configure DMA user callbacks */
+ hsd->hdmarx->XferCpltCallback = SD_DMA_RxCplt;
+ hsd->hdmarx->XferErrorCallback = SD_DMA_RxError;
+
+ /* Change DMA direction Periph to Memory */
+ hsd->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hsd->hdmarx->Instance->CCR &= ~DMA_MEMORY_TO_PERIPH;
+
+ /* Enable the DMA Channel */
+ HAL_DMA_Start_IT(hsd->hdmarx, (uint32_t)&hsd->Instance->FIFO, (uint32_t)pReadBuffer, (uint32_t)(BlockSize * NumberOfBlocks)/4);
+
+ if (hsd->CardType == HIGH_CAPACITY_SD_CARD)
+ {
+ BlockSize = 512;
+ ReadAddr /= 512;
+ }
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)BlockSize;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = BlockSize * NumberOfBlocks;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ /* Check number of blocks command */
+ if(NumberOfBlocks > 1)
+ {
+ /* Send CMD18 READ_MULT_BLOCK with argument data address */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_MULT_BLOCK;
+ }
+ else
+ {
+ /* Send CMD17 READ_SINGLE_BLOCK */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_SINGLE_BLOCK;
+ }
+
+ sdmmc_cmdinitstructure.Argument = (uint32_t)ReadAddr;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ if(NumberOfBlocks > 1)
+ {
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_READ_MULT_BLOCK);
+ }
+ else
+ {
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_READ_SINGLE_BLOCK);
+ }
+
+ /* Update the SD transfer error in SD handle */
+ hsd->SdTransferErr = errorstate;
+
+ return errorstate;
+}
+
+
+/**
+ * @brief Writes block(s) to a specified address in a card. The Data transfer
+ * is managed by DMA mode.
+ * @note This API should be followed by the function HAL_SD_CheckWriteOperation()
+ * to check the completion of the write process (by SD current status polling).
+ * @param hsd: SD handle
+ * @param pWriteBuffer: pointer to the buffer that will contain the data to transmit
+ * @param WriteAddr: Address from where data is to be read
+ * @param BlockSize: the SD card Data block size
+ * @note BlockSize must be 512 bytes.
+ * @param NumberOfBlocks: Number of blocks to write
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t *pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ /* Initialize data control register */
+ hsd->Instance->DCTRL = 0;
+
+ /* Initialize handle flags */
+ hsd->SdTransferCplt = 0;
+ hsd->DmaTransferCplt = 0;
+ hsd->SdTransferErr = SD_OK;
+
+ /* Initialize SD Write operation */
+ if(NumberOfBlocks > 1)
+ {
+ hsd->SdOperation = SD_WRITE_MULTIPLE_BLOCK;
+ }
+ else
+ {
+ hsd->SdOperation = SD_WRITE_SINGLE_BLOCK;
+ }
+
+ /* Enable transfer interrupts */
+ __HAL_SD_SDMMC_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL |\
+ SDMMC_IT_DTIMEOUT |\
+ SDMMC_IT_DATAEND |\
+ SDMMC_IT_TXUNDERR));
+
+ /* Configure DMA user callbacks */
+ hsd->hdmatx->XferCpltCallback = SD_DMA_TxCplt;
+ hsd->hdmatx->XferErrorCallback = SD_DMA_TxError;
+
+ /* Change DMA direction Memory to Periph */
+ hsd->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
+ hsd->hdmatx->Instance->CCR |= DMA_MEMORY_TO_PERIPH;
+
+ /* Enable the DMA Channel */
+ HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pWriteBuffer, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BlockSize * NumberOfBlocks)/4);
+
+ /* Enable SDMMC DMA transfer */
+ __HAL_SD_SDMMC_DMA_ENABLE(hsd);
+
+ if (hsd->CardType == HIGH_CAPACITY_SD_CARD)
+ {
+ BlockSize = 512;
+ WriteAddr /= 512;
+ }
+
+ /* Set Block Size for Card */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)BlockSize;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Check number of blocks command */
+ if(NumberOfBlocks <= 1)
+ {
+ /* Send CMD24 WRITE_SINGLE_BLOCK */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;
+ }
+ else
+ {
+ /* Send CMD25 WRITE_MULT_BLOCK with argument data address */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_MULT_BLOCK;
+ }
+
+ sdmmc_cmdinitstructure.Argument = (uint32_t)WriteAddr;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ if(NumberOfBlocks > 1)
+ {
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_WRITE_MULT_BLOCK);
+ }
+ else
+ {
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_WRITE_SINGLE_BLOCK);
+ }
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = BlockSize * NumberOfBlocks;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ hsd->SdTransferErr = errorstate;
+
+ return errorstate;
+}
+
+/**
+ * @brief This function waits until the SD DMA data read transfer is finished.
+ * This API should be called after HAL_SD_ReadBlocks_DMA() function
+ * to insure that all data sent by the card is already transferred by the
+ * DMA controller.
+ * @param hsd: SD handle
+ * @param Timeout: Timeout duration
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_CheckReadOperation(SD_HandleTypeDef *hsd, uint32_t Timeout)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t timeout = Timeout;
+ uint32_t tmp1, tmp2;
+ HAL_SD_ErrorTypedef tmp3;
+
+ /* Wait for DMA/SD transfer end or SD error variables to be in SD handle */
+ tmp1 = hsd->DmaTransferCplt;
+ tmp2 = hsd->SdTransferCplt;
+ tmp3 = (HAL_SD_ErrorTypedef)hsd->SdTransferErr;
+
+ while (((tmp1 & tmp2) == 0) && (tmp3 == SD_OK) && (timeout > 0))
+ {
+ tmp1 = hsd->DmaTransferCplt;
+ tmp2 = hsd->SdTransferCplt;
+ tmp3 = (HAL_SD_ErrorTypedef)hsd->SdTransferErr;
+ timeout--;
+ }
+
+ timeout = Timeout;
+
+ /* Wait until the Rx transfer is no longer active */
+ while((__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXACT)) && (timeout > 0))
+ {
+ timeout--;
+ }
+
+ /* Send stop command in multiblock read */
+ if (hsd->SdOperation == SD_READ_MULTIPLE_BLOCK)
+ {
+ errorstate = HAL_SD_StopTransfer(hsd);
+ }
+
+ if ((timeout == 0) && (errorstate == SD_OK))
+ {
+ errorstate = SD_DATA_TIMEOUT;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ /* Return error state */
+ if (hsd->SdTransferErr != SD_OK)
+ {
+ return (HAL_SD_ErrorTypedef)(hsd->SdTransferErr);
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief This function waits until the SD DMA data write transfer is finished.
+ * This API should be called after HAL_SD_WriteBlocks_DMA() function
+ * to insure that all data sent by the card is already transferred by the
+ * DMA controller.
+ * @param hsd: SD handle
+ * @param Timeout: Timeout duration
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_CheckWriteOperation(SD_HandleTypeDef *hsd, uint32_t Timeout)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t timeout = Timeout;
+ uint32_t tmp1, tmp2;
+ HAL_SD_ErrorTypedef tmp3;
+
+ /* Wait for DMA/SD transfer end or SD error variables to be in SD handle */
+ tmp1 = hsd->DmaTransferCplt;
+ tmp2 = hsd->SdTransferCplt;
+ tmp3 = (HAL_SD_ErrorTypedef)hsd->SdTransferErr;
+
+ while (((tmp1 & tmp2) == 0) && (tmp3 == SD_OK) && (timeout > 0))
+ {
+ tmp1 = hsd->DmaTransferCplt;
+ tmp2 = hsd->SdTransferCplt;
+ tmp3 = (HAL_SD_ErrorTypedef)hsd->SdTransferErr;
+ timeout--;
+ }
+
+ timeout = Timeout;
+
+ /* Wait until the Tx transfer is no longer active */
+ while((__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_TXACT)) && (timeout > 0))
+ {
+ timeout--;
+ }
+
+ /* Send stop command in multiblock write */
+ if (hsd->SdOperation == SD_WRITE_MULTIPLE_BLOCK)
+ {
+ errorstate = HAL_SD_StopTransfer(hsd);
+ }
+
+ if ((timeout == 0) && (errorstate == SD_OK))
+ {
+ errorstate = SD_DATA_TIMEOUT;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ /* Return error state */
+ if (hsd->SdTransferErr != SD_OK)
+ {
+ return (HAL_SD_ErrorTypedef)(hsd->SdTransferErr);
+ }
+
+ /* Wait until write is complete */
+ while(HAL_SD_GetStatus(hsd) != SD_TRANSFER_OK)
+ {
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Erases the specified memory area of the given SD card.
+ * @param hsd: SD handle
+ * @param startaddr: Start byte address
+ * @param endaddr: End byte address
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint64_t startaddr, uint64_t endaddr)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+
+ uint32_t delay = 0;
+ __IO uint32_t maxdelay = 0;
+ uint8_t cardstate = 0;
+
+ /* Check if the card command class supports erase command */
+ if (((hsd->CSD[1] >> 20) & SD_CCCC_ERASE) == 0)
+ {
+ errorstate = SD_REQUEST_NOT_APPLICABLE;
+
+ return errorstate;
+ }
+
+ /* Get max delay value */
+ maxdelay = 120000 / (((hsd->Instance->CLKCR) & 0xFF) + 2);
+
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SD_CARD_LOCKED) == SD_CARD_LOCKED)
+ {
+ errorstate = SD_LOCK_UNLOCK_FAILED;
+
+ return errorstate;
+ }
+
+ /* Get start and end block for high capacity cards */
+ if (hsd->CardType == HIGH_CAPACITY_SD_CARD)
+ {
+ startaddr /= 512;
+ endaddr /= 512;
+ }
+
+ /* According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
+ if ((hsd->CardType == STD_CAPACITY_SD_CARD_V1_1) || (hsd->CardType == STD_CAPACITY_SD_CARD_V2_0) ||\
+ (hsd->CardType == HIGH_CAPACITY_SD_CARD))
+ {
+ /* Send CMD32 SD_ERASE_GRP_START with argument as addr */
+ sdmmc_cmdinitstructure.Argument =(uint32_t)startaddr;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_ERASE_GRP_START;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SD_ERASE_GRP_START);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Send CMD33 SD_ERASE_GRP_END with argument as addr */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)endaddr;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_ERASE_GRP_END;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SD_ERASE_GRP_END);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+ }
+
+ /* Send CMD38 ERASE */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_ERASE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_ERASE);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ for (; delay < maxdelay; delay++)
+ {
+ }
+
+ /* Wait until the card is in programming state */
+ errorstate = SD_IsCardProgramming(hsd, &cardstate);
+
+ delay = SD_DATATIMEOUT;
+
+ while ((delay > 0) && (errorstate == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING)))
+ {
+ errorstate = SD_IsCardProgramming(hsd, &cardstate);
+ delay--;
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief This function handles SD card interrupt request.
+ * @param hsd: SD handle
+ * @retval None
+ */
+void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd)
+{
+ /* Check for SDMMC interrupt flags */
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_IT_DATAEND))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_IT_DATAEND);
+
+ /* SD transfer is complete */
+ hsd->SdTransferCplt = 1;
+
+ /* No transfer error */
+ hsd->SdTransferErr = SD_OK;
+
+ HAL_SD_XferCpltCallback(hsd);
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_IT_DCRCFAIL))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ hsd->SdTransferErr = SD_DATA_CRC_FAIL;
+
+ HAL_SD_XferErrorCallback(hsd);
+
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_IT_DTIMEOUT))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ hsd->SdTransferErr = SD_DATA_TIMEOUT;
+
+ HAL_SD_XferErrorCallback(hsd);
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_IT_RXOVERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ hsd->SdTransferErr = SD_RX_OVERRUN;
+
+ HAL_SD_XferErrorCallback(hsd);
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_IT_TXUNDERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_TXUNDERR);
+
+ hsd->SdTransferErr = SD_TX_UNDERRUN;
+
+ HAL_SD_XferErrorCallback(hsd);
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Disable all SDMMC peripheral interrupt sources */
+ __HAL_SD_SDMMC_DISABLE_IT(hsd, SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_DATAEND |\
+ SDMMC_IT_TXFIFOHE | SDMMC_IT_RXFIFOHF | SDMMC_IT_TXUNDERR |\
+ SDMMC_IT_RXOVERR);
+}
+
+
+/**
+ * @brief SD end of transfer callback.
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SD_XferCpltCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_XferCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD Transfer Error callback.
+ * @param hsd: SD handle
+ * @retval None
+ */
+__weak void HAL_SD_XferErrorCallback(SD_HandleTypeDef *hsd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_XferErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD Transfer complete Rx callback in non-blocking mode.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+__weak void HAL_SD_DMA_RxCpltCallback(DMA_HandleTypeDef *hdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_DMA_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD DMA transfer complete Rx error callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+__weak void HAL_SD_DMA_RxErrorCallback(DMA_HandleTypeDef *hdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_DMA_RxErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD Transfer complete Tx callback in non-blocking mode.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+__weak void HAL_SD_DMA_TxCpltCallback(DMA_HandleTypeDef *hdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_DMA_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SD DMA transfer complete error Tx callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+__weak void HAL_SD_DMA_TxErrorCallback(DMA_HandleTypeDef *hdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hdma);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SD_DMA_TxErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup SD_Exported_Functions_Group3
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SD card
+ operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns information about specific card.
+ * @param hsd: SD handle
+ * @param pCardInfo: Pointer to a HAL_SD_CardInfoTypedef structure that
+ * contains all SD cardinformation
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_Get_CardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *pCardInfo)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t tmp = 0;
+
+ pCardInfo->CardType = (uint8_t)(hsd->CardType);
+ pCardInfo->RCA = (uint16_t)(hsd->RCA);
+
+ /* Byte 0 */
+ tmp = (hsd->CSD[0] & 0xFF000000) >> 24;
+ pCardInfo->SD_csd.CSDStruct = (uint8_t)((tmp & 0xC0) >> 6);
+ pCardInfo->SD_csd.SysSpecVersion = (uint8_t)((tmp & 0x3C) >> 2);
+ pCardInfo->SD_csd.Reserved1 = tmp & 0x03;
+
+ /* Byte 1 */
+ tmp = (hsd->CSD[0] & 0x00FF0000) >> 16;
+ pCardInfo->SD_csd.TAAC = (uint8_t)tmp;
+
+ /* Byte 2 */
+ tmp = (hsd->CSD[0] & 0x0000FF00) >> 8;
+ pCardInfo->SD_csd.NSAC = (uint8_t)tmp;
+
+ /* Byte 3 */
+ tmp = hsd->CSD[0] & 0x000000FF;
+ pCardInfo->SD_csd.MaxBusClkFrec = (uint8_t)tmp;
+
+ /* Byte 4 */
+ tmp = (hsd->CSD[1] & 0xFF000000) >> 24;
+ pCardInfo->SD_csd.CardComdClasses = (uint16_t)(tmp << 4);
+
+ /* Byte 5 */
+ tmp = (hsd->CSD[1] & 0x00FF0000) >> 16;
+ pCardInfo->SD_csd.CardComdClasses |= (uint16_t)((tmp & 0xF0) >> 4);
+ pCardInfo->SD_csd.RdBlockLen = (uint8_t)(tmp & 0x0F);
+
+ /* Byte 6 */
+ tmp = (hsd->CSD[1] & 0x0000FF00) >> 8;
+ pCardInfo->SD_csd.PartBlockRead = (uint8_t)((tmp & 0x80) >> 7);
+ pCardInfo->SD_csd.WrBlockMisalign = (uint8_t)((tmp & 0x40) >> 6);
+ pCardInfo->SD_csd.RdBlockMisalign = (uint8_t)((tmp & 0x20) >> 5);
+ pCardInfo->SD_csd.DSRImpl = (uint8_t)((tmp & 0x10) >> 4);
+ pCardInfo->SD_csd.Reserved2 = 0; /*!< Reserved */
+
+ if ((hsd->CardType == STD_CAPACITY_SD_CARD_V1_1) || (hsd->CardType == STD_CAPACITY_SD_CARD_V2_0))
+ {
+ pCardInfo->SD_csd.DeviceSize = (tmp & 0x03) << 10;
+
+ /* Byte 7 */
+ tmp = (uint8_t)(hsd->CSD[1] & 0x000000FF);
+ pCardInfo->SD_csd.DeviceSize |= (tmp) << 2;
+
+ /* Byte 8 */
+ tmp = (uint8_t)((hsd->CSD[2] & 0xFF000000) >> 24);
+ pCardInfo->SD_csd.DeviceSize |= (tmp & 0xC0) >> 6;
+
+ pCardInfo->SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
+ pCardInfo->SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07);
+
+ /* Byte 9 */
+ tmp = (uint8_t)((hsd->CSD[2] & 0x00FF0000) >> 16);
+ pCardInfo->SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
+ pCardInfo->SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
+ pCardInfo->SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;
+ /* Byte 10 */
+ tmp = (uint8_t)((hsd->CSD[2] & 0x0000FF00) >> 8);
+ pCardInfo->SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;
+
+ pCardInfo->CardCapacity = (pCardInfo->SD_csd.DeviceSize + 1) ;
+ pCardInfo->CardCapacity *= (1 << (pCardInfo->SD_csd.DeviceSizeMul + 2));
+ pCardInfo->CardBlockSize = 1 << (pCardInfo->SD_csd.RdBlockLen);
+ pCardInfo->CardCapacity *= pCardInfo->CardBlockSize;
+ }
+ else if (hsd->CardType == HIGH_CAPACITY_SD_CARD)
+ {
+ /* Byte 7 */
+ tmp = (uint8_t)(hsd->CSD[1] & 0x000000FF);
+ pCardInfo->SD_csd.DeviceSize = (tmp & 0x3F) << 16;
+
+ /* Byte 8 */
+ tmp = (uint8_t)((hsd->CSD[2] & 0xFF000000) >> 24);
+
+ pCardInfo->SD_csd.DeviceSize |= (tmp << 8);
+
+ /* Byte 9 */
+ tmp = (uint8_t)((hsd->CSD[2] & 0x00FF0000) >> 16);
+
+ pCardInfo->SD_csd.DeviceSize |= (tmp);
+
+ /* Byte 10 */
+ tmp = (uint8_t)((hsd->CSD[2] & 0x0000FF00) >> 8);
+
+ pCardInfo->CardCapacity = (uint64_t)(((uint64_t)pCardInfo->SD_csd.DeviceSize + 1) * 512 * 1024);
+ pCardInfo->CardBlockSize = 512;
+ }
+ else
+ {
+ /* Not supported card type */
+ errorstate = SD_ERROR;
+ }
+
+ pCardInfo->SD_csd.EraseGrSize = (tmp & 0x40) >> 6;
+ pCardInfo->SD_csd.EraseGrMul = (tmp & 0x3F) << 1;
+
+ /* Byte 11 */
+ tmp = (uint8_t)(hsd->CSD[2] & 0x000000FF);
+ pCardInfo->SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
+ pCardInfo->SD_csd.WrProtectGrSize = (tmp & 0x7F);
+
+ /* Byte 12 */
+ tmp = (uint8_t)((hsd->CSD[3] & 0xFF000000) >> 24);
+ pCardInfo->SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7;
+ pCardInfo->SD_csd.ManDeflECC = (tmp & 0x60) >> 5;
+ pCardInfo->SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2;
+ pCardInfo->SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2;
+
+ /* Byte 13 */
+ tmp = (uint8_t)((hsd->CSD[3] & 0x00FF0000) >> 16);
+ pCardInfo->SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6;
+ pCardInfo->SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5;
+ pCardInfo->SD_csd.Reserved3 = 0;
+ pCardInfo->SD_csd.ContentProtectAppli = (tmp & 0x01);
+
+ /* Byte 14 */
+ tmp = (uint8_t)((hsd->CSD[3] & 0x0000FF00) >> 8);
+ pCardInfo->SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7;
+ pCardInfo->SD_csd.CopyFlag = (tmp & 0x40) >> 6;
+ pCardInfo->SD_csd.PermWrProtect = (tmp & 0x20) >> 5;
+ pCardInfo->SD_csd.TempWrProtect = (tmp & 0x10) >> 4;
+ pCardInfo->SD_csd.FileFormat = (tmp & 0x0C) >> 2;
+ pCardInfo->SD_csd.ECC = (tmp & 0x03);
+
+ /* Byte 15 */
+ tmp = (uint8_t)(hsd->CSD[3] & 0x000000FF);
+ pCardInfo->SD_csd.CSD_CRC = (tmp & 0xFE) >> 1;
+ pCardInfo->SD_csd.Reserved4 = 1;
+
+ /* Byte 0 */
+ tmp = (uint8_t)((hsd->CID[0] & 0xFF000000) >> 24);
+ pCardInfo->SD_cid.ManufacturerID = tmp;
+
+ /* Byte 1 */
+ tmp = (uint8_t)((hsd->CID[0] & 0x00FF0000) >> 16);
+ pCardInfo->SD_cid.OEM_AppliID = tmp << 8;
+
+ /* Byte 2 */
+ tmp = (uint8_t)((hsd->CID[0] & 0x000000FF00) >> 8);
+ pCardInfo->SD_cid.OEM_AppliID |= tmp;
+
+ /* Byte 3 */
+ tmp = (uint8_t)(hsd->CID[0] & 0x000000FF);
+ pCardInfo->SD_cid.ProdName1 = tmp << 24;
+
+ /* Byte 4 */
+ tmp = (uint8_t)((hsd->CID[1] & 0xFF000000) >> 24);
+ pCardInfo->SD_cid.ProdName1 |= tmp << 16;
+
+ /* Byte 5 */
+ tmp = (uint8_t)((hsd->CID[1] & 0x00FF0000) >> 16);
+ pCardInfo->SD_cid.ProdName1 |= tmp << 8;
+
+ /* Byte 6 */
+ tmp = (uint8_t)((hsd->CID[1] & 0x0000FF00) >> 8);
+ pCardInfo->SD_cid.ProdName1 |= tmp;
+
+ /* Byte 7 */
+ tmp = (uint8_t)(hsd->CID[1] & 0x000000FF);
+ pCardInfo->SD_cid.ProdName2 = tmp;
+
+ /* Byte 8 */
+ tmp = (uint8_t)((hsd->CID[2] & 0xFF000000) >> 24);
+ pCardInfo->SD_cid.ProdRev = tmp;
+
+ /* Byte 9 */
+ tmp = (uint8_t)((hsd->CID[2] & 0x00FF0000) >> 16);
+ pCardInfo->SD_cid.ProdSN = tmp << 24;
+
+ /* Byte 10 */
+ tmp = (uint8_t)((hsd->CID[2] & 0x0000FF00) >> 8);
+ pCardInfo->SD_cid.ProdSN |= tmp << 16;
+
+ /* Byte 11 */
+ tmp = (uint8_t)(hsd->CID[2] & 0x000000FF);
+ pCardInfo->SD_cid.ProdSN |= tmp << 8;
+
+ /* Byte 12 */
+ tmp = (uint8_t)((hsd->CID[3] & 0xFF000000) >> 24);
+ pCardInfo->SD_cid.ProdSN |= tmp;
+
+ /* Byte 13 */
+ tmp = (uint8_t)((hsd->CID[3] & 0x00FF0000) >> 16);
+ pCardInfo->SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
+ pCardInfo->SD_cid.ManufactDate = (tmp & 0x0F) << 8;
+
+ /* Byte 14 */
+ tmp = (uint8_t)((hsd->CID[3] & 0x0000FF00) >> 8);
+ pCardInfo->SD_cid.ManufactDate |= tmp;
+
+ /* Byte 15 */
+ tmp = (uint8_t)(hsd->CID[3] & 0x000000FF);
+ pCardInfo->SD_cid.CID_CRC = (tmp & 0xFE) >> 1;
+ pCardInfo->SD_cid.Reserved2 = 1;
+
+ return errorstate;
+}
+
+/**
+ * @brief Enables wide bus operation for the requested card if supported by
+ * card.
+ * @param hsd: SD handle
+ * @param WideMode: Specifies the SD card wide bus mode
+ * This parameter can be one of the following values:
+ * @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer (Only for MMC)
+ * @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
+ * @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_WideBusOperation_Config(SD_HandleTypeDef *hsd, uint32_t WideMode)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ SDMMC_InitTypeDef tmpinit;
+
+ /* MMC Card does not support this feature */
+ if (hsd->CardType == MULTIMEDIA_CARD)
+ {
+ errorstate = SD_UNSUPPORTED_FEATURE;
+
+ return errorstate;
+ }
+ else if ((hsd->CardType == STD_CAPACITY_SD_CARD_V1_1) || (hsd->CardType == STD_CAPACITY_SD_CARD_V2_0) ||\
+ (hsd->CardType == HIGH_CAPACITY_SD_CARD))
+ {
+ if (WideMode == SDMMC_BUS_WIDE_8B)
+ {
+ errorstate = SD_UNSUPPORTED_FEATURE;
+ }
+ else if (WideMode == SDMMC_BUS_WIDE_4B)
+ {
+ errorstate = SD_WideBus_Enable(hsd);
+ }
+ else if (WideMode == SDMMC_BUS_WIDE_1B)
+ {
+ errorstate = SD_WideBus_Disable(hsd);
+ }
+ else
+ {
+ /* WideMode is not a valid argument*/
+ errorstate = SD_INVALID_PARAMETER;
+ }
+
+ if (errorstate == SD_OK)
+ {
+ /* Configure the SDMMC peripheral */
+ tmpinit.ClockEdge = hsd->Init.ClockEdge;
+ tmpinit.ClockBypass = hsd->Init.ClockBypass;
+ tmpinit.ClockPowerSave = hsd->Init.ClockPowerSave;
+ tmpinit.BusWide = WideMode;
+ tmpinit.HardwareFlowControl = hsd->Init.HardwareFlowControl;
+ tmpinit.ClockDiv = hsd->Init.ClockDiv;
+ SDMMC_Init(hsd->Instance, tmpinit);
+ }
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Aborts an ongoing data transfer.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_StopTransfer(SD_HandleTypeDef *hsd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ /* Send CMD12 STOP_TRANSMISSION */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_STOP_TRANSMISSION;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_STOP_TRANSMISSION);
+
+ return errorstate;
+}
+
+/**
+ * @brief Switches the SD card to High Speed mode.
+ * This API must be used after "Transfer State"
+ * @note This operation should be followed by the configuration
+ * of PLL to have SDMMCCK clock between 67 and 75 MHz
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_HighSpeed (SD_HandleTypeDef *hsd)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+
+ uint8_t SD_hs[64] = {0};
+ uint32_t SD_scr[2] = {0, 0};
+ uint32_t SD_SPEC = 0 ;
+ uint32_t count = 0, *tempbuff = (uint32_t *)SD_hs;
+
+ /* Initialize the Data control register */
+ hsd->Instance->DCTRL = 0;
+
+ /* Get SCR Register */
+ errorstate = SD_FindSCR(hsd, SD_scr);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Test the Version supported by the card*/
+ SD_SPEC = (SD_scr[1] & 0x01000000) | (SD_scr[1] & 0x02000000);
+
+ if (SD_SPEC != SD_ALLZERO)
+ {
+ /* Set Block Size for Card */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)64;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = 64;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B ;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ /* Send CMD6 switch mode */
+ sdmmc_cmdinitstructure.Argument = 0x80FFFF01;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_HS_SWITCH;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_HS_SWITCH);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
+ {
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ for (count = 0; count < 8; count++)
+ {
+ *(tempbuff + count) = SDMMC_ReadFIFO(hsd->Instance);
+ }
+
+ tempbuff += 8;
+ }
+ }
+
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ errorstate = SD_DATA_TIMEOUT;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SD_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SD_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ count = SD_DATATIMEOUT;
+
+ while ((__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL)) && (count > 0))
+ {
+ *tempbuff = SDMMC_ReadFIFO(hsd->Instance);
+ tempbuff++;
+ count--;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ /* Test if the switch mode HS is ok */
+ if ((SD_hs[13]& 2) != 2)
+ {
+ errorstate = SD_UNSUPPORTED_FEATURE;
+ }
+ }
+
+ return errorstate;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup SD_Exported_Functions_Group4
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in runtime the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the current SD card's status.
+ * @param hsd: SD handle
+ * @param pSDstatus: Pointer to the buffer that will contain the SD card status
+ * SD Status register)
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t count = 0;
+
+ /* Check SD response */
+ if ((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SD_CARD_LOCKED) == SD_CARD_LOCKED)
+ {
+ errorstate = SD_LOCK_UNLOCK_FAILED;
+
+ return errorstate;
+ }
+
+ /* Set block size for card if it is not equal to current block size for card */
+ sdmmc_cmdinitstructure.Argument = 64;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Send CMD55 */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)(hsd->RCA << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_CMD);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Configure the SD DPSM (Data Path State Machine) */
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = 64;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_64B;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ /* Send ACMD13 (SD_APP_STAUS) with argument as card's RCA */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_APP_STATUS;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SD_APP_STATUS);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Get status data */
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
+ {
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF))
+ {
+ for (count = 0; count < 8; count++)
+ {
+ *(pSDstatus + count) = SDMMC_ReadFIFO(hsd->Instance);
+ }
+
+ pSDstatus += 8;
+ }
+ }
+
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ errorstate = SD_DATA_TIMEOUT;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SD_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SD_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ count = SD_DATATIMEOUT;
+ while ((__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL)) && (count > 0))
+ {
+ *pSDstatus = SDMMC_ReadFIFO(hsd->Instance);
+ pSDstatus++;
+ count--;
+ }
+
+ /* Clear all the static status flags*/
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ return errorstate;
+}
+
+/**
+ * @brief Gets the current sd card data status.
+ * @param hsd: SD handle
+ * @retval Data Transfer state
+ */
+HAL_SD_TransferStateTypedef HAL_SD_GetStatus(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_CardStateTypedef cardstate = SD_CARD_TRANSFER;
+
+ /* Get SD card state */
+ cardstate = SD_GetState(hsd);
+
+ /* Find SD status according to card state*/
+ if (cardstate == SD_CARD_TRANSFER)
+ {
+ return SD_TRANSFER_OK;
+ }
+ else if(cardstate == SD_CARD_ERROR)
+ {
+ return SD_TRANSFER_ERROR;
+ }
+ else
+ {
+ return SD_TRANSFER_BUSY;
+ }
+}
+
+/**
+ * @brief Gets the SD card status.
+ * @param hsd: SD handle
+ * @param pCardStatus: Pointer to the HAL_SD_CardStatusTypedef structure that
+ * will contain the SD card status information
+ * @retval SD Card error state
+ */
+HAL_SD_ErrorTypedef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypedef *pCardStatus)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t tmp = 0;
+ uint32_t sd_status[16];
+
+ errorstate = HAL_SD_SendSDStatus(hsd, sd_status);
+
+ if (errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Byte 0 */
+ tmp = (sd_status[0] & 0xC0) >> 6;
+ pCardStatus->DAT_BUS_WIDTH = (uint8_t)tmp;
+
+ /* Byte 0 */
+ tmp = (sd_status[0] & 0x20) >> 5;
+ pCardStatus->SECURED_MODE = (uint8_t)tmp;
+
+ /* Byte 2 */
+ tmp = (sd_status[2] & 0xFF);
+ pCardStatus->SD_CARD_TYPE = (uint8_t)(tmp << 8);
+
+ /* Byte 3 */
+ tmp = (sd_status[3] & 0xFF);
+ pCardStatus->SD_CARD_TYPE |= (uint8_t)tmp;
+
+ /* Byte 4 */
+ tmp = (sd_status[4] & 0xFF);
+ pCardStatus->SIZE_OF_PROTECTED_AREA = (uint8_t)(tmp << 24);
+
+ /* Byte 5 */
+ tmp = (sd_status[5] & 0xFF);
+ pCardStatus->SIZE_OF_PROTECTED_AREA |= (uint8_t)(tmp << 16);
+
+ /* Byte 6 */
+ tmp = (sd_status[6] & 0xFF);
+ pCardStatus->SIZE_OF_PROTECTED_AREA |= (uint8_t)(tmp << 8);
+
+ /* Byte 7 */
+ tmp = (sd_status[7] & 0xFF);
+ pCardStatus->SIZE_OF_PROTECTED_AREA |= (uint8_t)tmp;
+
+ /* Byte 8 */
+ tmp = (sd_status[8] & 0xFF);
+ pCardStatus->SPEED_CLASS = (uint8_t)tmp;
+
+ /* Byte 9 */
+ tmp = (sd_status[9] & 0xFF);
+ pCardStatus->PERFORMANCE_MOVE = (uint8_t)tmp;
+
+ /* Byte 10 */
+ tmp = (sd_status[10] & 0xF0) >> 4;
+ pCardStatus->AU_SIZE = (uint8_t)tmp;
+
+ /* Byte 11 */
+ tmp = (sd_status[11] & 0xFF);
+ pCardStatus->ERASE_SIZE = (uint8_t)(tmp << 8);
+
+ /* Byte 12 */
+ tmp = (sd_status[12] & 0xFF);
+ pCardStatus->ERASE_SIZE |= (uint8_t)tmp;
+
+ /* Byte 13 */
+ tmp = (sd_status[13] & 0xFC) >> 2;
+ pCardStatus->ERASE_TIMEOUT = (uint8_t)tmp;
+
+ /* Byte 13 */
+ tmp = (sd_status[13] & 0x3);
+ pCardStatus->ERASE_OFFSET = (uint8_t)tmp;
+
+ return errorstate;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private function ----------------------------------------------------------*/
+/** @addtogroup SD_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief SD DMA transfer complete Rx callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SD_DMA_RxCplt(DMA_HandleTypeDef *hdma)
+{
+ SD_HandleTypeDef *hsd = (SD_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* DMA transfer is complete */
+ hsd->DmaTransferCplt = 1;
+
+ /* Wait until SD transfer is complete */
+ while(hsd->SdTransferCplt == 0)
+ {
+ }
+
+ /* Disable the DMA channel */
+ HAL_DMA_Abort(hdma);
+
+ /* Transfer complete user callback */
+ HAL_SD_DMA_RxCpltCallback(hsd->hdmarx);
+}
+
+/**
+ * @brief SD DMA transfer Error Rx callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SD_DMA_RxError(DMA_HandleTypeDef *hdma)
+{
+ SD_HandleTypeDef *hsd = (SD_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Transfer complete user callback */
+ HAL_SD_DMA_RxErrorCallback(hsd->hdmarx);
+}
+
+/**
+ * @brief SD DMA transfer complete Tx callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SD_DMA_TxCplt(DMA_HandleTypeDef *hdma)
+{
+ SD_HandleTypeDef *hsd = (SD_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* DMA transfer is complete */
+ hsd->DmaTransferCplt = 1;
+
+ /* Wait until SD transfer is complete */
+ while(hsd->SdTransferCplt == 0)
+ {
+ }
+
+ /* Disable the DMA channel */
+ HAL_DMA_Abort(hdma);
+
+ /* Transfer complete user callback */
+ HAL_SD_DMA_TxCpltCallback(hsd->hdmatx);
+}
+
+/**
+ * @brief SD DMA transfer Error Tx callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SD_DMA_TxError(DMA_HandleTypeDef *hdma)
+{
+ SD_HandleTypeDef *hsd = ( SD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Transfer complete user callback */
+ HAL_SD_DMA_TxErrorCallback(hsd->hdmatx);
+}
+
+/**
+ * @brief Returns the SD current state.
+ * @param hsd: SD handle
+ * @retval SD card current state
+ */
+static HAL_SD_CardStateTypedef SD_GetState(SD_HandleTypeDef *hsd)
+{
+ uint32_t resp1 = 0;
+
+ if (SD_SendStatus(hsd, &resp1) != SD_OK)
+ {
+ return SD_CARD_ERROR;
+ }
+ else
+ {
+ return (HAL_SD_CardStateTypedef)((resp1 >> 9) & 0x0F);
+ }
+}
+
+/**
+ * @brief Initializes all cards or single card as the case may be Card(s) come
+ * into standby state.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_Initialize_Cards(SD_HandleTypeDef *hsd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint16_t sd_rca = 1;
+
+ if(SDMMC_GetPowerState(hsd->Instance) == 0) /* Power off */
+ {
+ errorstate = SD_REQUEST_NOT_APPLICABLE;
+
+ return errorstate;
+ }
+
+ if(hsd->CardType != SECURE_DIGITAL_IO_CARD)
+ {
+ /* Send CMD2 ALL_SEND_CID */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_ALL_SEND_CID;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_LONG;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp2Error(hsd);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Get Card identification number data */
+ hsd->CID[0] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+ hsd->CID[1] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP2);
+ hsd->CID[2] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP3);
+ hsd->CID[3] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP4);
+ }
+
+ if((hsd->CardType == STD_CAPACITY_SD_CARD_V1_1) || (hsd->CardType == STD_CAPACITY_SD_CARD_V2_0) ||\
+ (hsd->CardType == SECURE_DIGITAL_IO_COMBO_CARD) || (hsd->CardType == HIGH_CAPACITY_SD_CARD))
+ {
+ /* Send CMD3 SET_REL_ADDR with argument 0 */
+ /* SD Card publishes its RCA. */
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_REL_ADDR;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp6Error(hsd, SD_CMD_SET_REL_ADDR, &sd_rca);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+ }
+
+ if (hsd->CardType != SECURE_DIGITAL_IO_CARD)
+ {
+ /* Get the SD card RCA */
+ hsd->RCA = sd_rca;
+
+ /* Send CMD9 SEND_CSD with argument as card's RCA */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)(hsd->RCA << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEND_CSD;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_LONG;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp2Error(hsd);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Get Card Specific Data */
+ hsd->CSD[0] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+ hsd->CSD[1] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP2);
+ hsd->CSD[2] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP3);
+ hsd->CSD[3] = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP4);
+ }
+
+ /* All cards are initialized */
+ return errorstate;
+}
+
+/**
+ * @brief Selects or Deselects the corresponding card.
+ * @param hsd: SD handle
+ * @param addr: Address of the card to be selected
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_Select_Deselect(SD_HandleTypeDef *hsd, uint64_t addr)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ /* Send CMD7 SDMMC_SEL_DESEL_CARD */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)addr;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEL_DESEL_CARD;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SEL_DESEL_CARD);
+
+ return errorstate;
+}
+
+/**
+ * @brief Enquires cards about their operating voltage and configures clock
+ * controls and stores SD information that will be needed in future
+ * in the SD handle.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_PowerON(SD_HandleTypeDef *hsd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ __IO HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t response = 0, count = 0, validvoltage = 0;
+ uint32_t sdtype = SD_STD_CAPACITY;
+
+ /* Power ON Sequence -------------------------------------------------------*/
+ /* Disable SDMMC Clock */
+ __HAL_SD_SDMMC_DISABLE(hsd);
+
+ /* Set Power State to ON */
+ SDMMC_PowerState_ON(hsd->Instance);
+
+ /* 1ms: required power up waiting time before starting the SD initialization
+ sequence */
+ HAL_Delay(1);
+
+ /* Enable SDMMC Clock */
+ __HAL_SD_SDMMC_ENABLE(hsd);
+
+ /* CMD0: GO_IDLE_STATE -----------------------------------------------------*/
+ /* No CMD response required */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_GO_IDLE_STATE;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_NO;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdError(hsd);
+
+ if(errorstate != SD_OK)
+ {
+ /* CMD Response Timeout (wait for CMDSENT flag) */
+ return errorstate;
+ }
+
+ /* CMD8: SEND_IF_COND ------------------------------------------------------*/
+ /* Send CMD8 to verify SD card interface operating condition */
+ /* Argument: - [31:12]: Reserved (shall be set to '0')
+ - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
+ - [7:0]: Check Pattern (recommended 0xAA) */
+ /* CMD Response: R7 */
+ sdmmc_cmdinitstructure.Argument = SD_CHECK_PATTERN;
+ sdmmc_cmdinitstructure.CmdIndex = SD_SDMMC_SEND_IF_COND;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp7Error(hsd);
+
+ if (errorstate == SD_OK)
+ {
+ /* SD Card 2.0 */
+ hsd->CardType = STD_CAPACITY_SD_CARD_V2_0;
+ sdtype = SD_HIGH_CAPACITY;
+ }
+
+ /* Send CMD55 */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_CMD);
+
+ /* If errorstate is Command Timeout, it is a MMC card */
+ /* If errorstate is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch)
+ or SD card 1.x */
+ if(errorstate == SD_OK)
+ {
+ /* SD CARD */
+ /* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
+ while((!validvoltage) && (count < SD_MAX_VOLT_TRIAL))
+ {
+
+ /* SEND CMD55 APP_CMD with RCA as 0 */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_CMD);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Send CMD41 */
+ sdmmc_cmdinitstructure.Argument = SD_VOLTAGE_WINDOW_SD | sdtype;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_APP_OP_COND;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp3Error(hsd);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Get command response */
+ response = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ /* Get operating voltage*/
+ validvoltage = (((response >> 31) == 1) ? 1 : 0);
+
+ count++;
+ }
+
+ if(count >= SD_MAX_VOLT_TRIAL)
+ {
+ errorstate = SD_INVALID_VOLTRANGE;
+
+ return errorstate;
+ }
+
+ if((response & SD_HIGH_CAPACITY) == SD_HIGH_CAPACITY) /* (response &= SD_HIGH_CAPACITY) */
+ {
+ hsd->CardType = HIGH_CAPACITY_SD_CARD;
+ }
+
+ } /* else MMC Card */
+
+ return errorstate;
+}
+
+/**
+ * @brief Turns the SDMMC output signals off.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_PowerOFF(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ /* Set Power State to OFF */
+ SDMMC_PowerState_OFF(hsd->Instance);
+
+ return errorstate;
+}
+
+/**
+ * @brief Returns the current card's status.
+ * @param hsd: SD handle
+ * @param pCardStatus: pointer to the buffer that will contain the SD card
+ * status (Card Status register)
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ if(pCardStatus == NULL)
+ {
+ errorstate = SD_INVALID_PARAMETER;
+
+ return errorstate;
+ }
+
+ /* Send Status command */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)(hsd->RCA << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEND_STATUS;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SEND_STATUS);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Get SD card status */
+ *pCardStatus = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks for error conditions for CMD0.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_CmdError(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t timeout, tmp;
+
+ timeout = SDMMC_CMD0TIMEOUT;
+
+ tmp = __HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CMDSENT);
+
+ while((timeout > 0) && (!tmp))
+ {
+ tmp = __HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CMDSENT);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ errorstate = SD_CMD_RSP_TIMEOUT;
+ return errorstate;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks for error conditions for R7 response.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_CmdResp7Error(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_ERROR;
+ uint32_t timeout = SDMMC_CMD0TIMEOUT, tmp;
+
+ tmp = __HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT);
+
+ while((!tmp) && (timeout > 0))
+ {
+ tmp = __HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT);
+ timeout--;
+ }
+
+ tmp = __HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ if((timeout == 0) || tmp)
+ {
+ /* Card is not V2.0 compliant or card does not support the set voltage range */
+ errorstate = SD_CMD_RSP_TIMEOUT;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ return errorstate;
+ }
+
+ if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CMDREND))
+ {
+ /* Card is SD V2.0 compliant */
+ errorstate = SD_OK;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CMDREND);
+
+ return errorstate;
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks for error conditions for R1 response.
+ * @param hsd: SD handle
+ * @param SD_CMD: The sent command index
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_CmdResp1Error(SD_HandleTypeDef *hsd, uint8_t SD_CMD)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t response_r1;
+
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT))
+ {
+ }
+
+ if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CTIMEOUT))
+ {
+ errorstate = SD_CMD_RSP_TIMEOUT;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ return errorstate;
+ }
+ else if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL))
+ {
+ errorstate = SD_CMD_CRC_FAIL;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CCRCFAIL);
+
+ return errorstate;
+ }
+
+ /* Check response received is of desired command */
+ if(SDMMC_GetCommandResponse(hsd->Instance) != SD_CMD)
+ {
+ errorstate = SD_ILLEGAL_CMD;
+
+ return errorstate;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ /* We have received response, retrieve it for analysis */
+ response_r1 = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ if((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO)
+ {
+ return errorstate;
+ }
+
+ if((response_r1 & SD_OCR_ADDR_OUT_OF_RANGE) == SD_OCR_ADDR_OUT_OF_RANGE)
+ {
+ return(SD_ADDR_OUT_OF_RANGE);
+ }
+
+ if((response_r1 & SD_OCR_ADDR_MISALIGNED) == SD_OCR_ADDR_MISALIGNED)
+ {
+ return(SD_ADDR_MISALIGNED);
+ }
+
+ if((response_r1 & SD_OCR_BLOCK_LEN_ERR) == SD_OCR_BLOCK_LEN_ERR)
+ {
+ return(SD_BLOCK_LEN_ERR);
+ }
+
+ if((response_r1 & SD_OCR_ERASE_SEQ_ERR) == SD_OCR_ERASE_SEQ_ERR)
+ {
+ return(SD_ERASE_SEQ_ERR);
+ }
+
+ if((response_r1 & SD_OCR_BAD_ERASE_PARAM) == SD_OCR_BAD_ERASE_PARAM)
+ {
+ return(SD_BAD_ERASE_PARAM);
+ }
+
+ if((response_r1 & SD_OCR_WRITE_PROT_VIOLATION) == SD_OCR_WRITE_PROT_VIOLATION)
+ {
+ return(SD_WRITE_PROT_VIOLATION);
+ }
+
+ if((response_r1 & SD_OCR_LOCK_UNLOCK_FAILED) == SD_OCR_LOCK_UNLOCK_FAILED)
+ {
+ return(SD_LOCK_UNLOCK_FAILED);
+ }
+
+ if((response_r1 & SD_OCR_COM_CRC_FAILED) == SD_OCR_COM_CRC_FAILED)
+ {
+ return(SD_COM_CRC_FAILED);
+ }
+
+ if((response_r1 & SD_OCR_ILLEGAL_CMD) == SD_OCR_ILLEGAL_CMD)
+ {
+ return(SD_ILLEGAL_CMD);
+ }
+
+ if((response_r1 & SD_OCR_CARD_ECC_FAILED) == SD_OCR_CARD_ECC_FAILED)
+ {
+ return(SD_CARD_ECC_FAILED);
+ }
+
+ if((response_r1 & SD_OCR_CC_ERROR) == SD_OCR_CC_ERROR)
+ {
+ return(SD_CC_ERROR);
+ }
+
+ if((response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR) == SD_OCR_GENERAL_UNKNOWN_ERROR)
+ {
+ return(SD_GENERAL_UNKNOWN_ERROR);
+ }
+
+ if((response_r1 & SD_OCR_STREAM_READ_UNDERRUN) == SD_OCR_STREAM_READ_UNDERRUN)
+ {
+ return(SD_STREAM_READ_UNDERRUN);
+ }
+
+ if((response_r1 & SD_OCR_STREAM_WRITE_OVERRUN) == SD_OCR_STREAM_WRITE_OVERRUN)
+ {
+ return(SD_STREAM_WRITE_OVERRUN);
+ }
+
+ if((response_r1 & SD_OCR_CID_CSD_OVERWRITE) == SD_OCR_CID_CSD_OVERWRITE)
+ {
+ return(SD_CID_CSD_OVERWRITE);
+ }
+
+ if((response_r1 & SD_OCR_WP_ERASE_SKIP) == SD_OCR_WP_ERASE_SKIP)
+ {
+ return(SD_WP_ERASE_SKIP);
+ }
+
+ if((response_r1 & SD_OCR_CARD_ECC_DISABLED) == SD_OCR_CARD_ECC_DISABLED)
+ {
+ return(SD_CARD_ECC_DISABLED);
+ }
+
+ if((response_r1 & SD_OCR_ERASE_RESET) == SD_OCR_ERASE_RESET)
+ {
+ return(SD_ERASE_RESET);
+ }
+
+ if((response_r1 & SD_OCR_AKE_SEQ_ERROR) == SD_OCR_AKE_SEQ_ERROR)
+ {
+ return(SD_AKE_SEQ_ERROR);
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks for error conditions for R3 (OCR) response.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_CmdResp3Error(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ while (!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT))
+ {
+ }
+
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CTIMEOUT))
+ {
+ errorstate = SD_CMD_RSP_TIMEOUT;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ return errorstate;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks for error conditions for R2 (CID or CSD) response.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_CmdResp2Error(SD_HandleTypeDef *hsd)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ while (!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT))
+ {
+ }
+
+ if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CTIMEOUT))
+ {
+ errorstate = SD_CMD_RSP_TIMEOUT;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ return errorstate;
+ }
+ else if (__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL))
+ {
+ errorstate = SD_CMD_CRC_FAIL;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CCRCFAIL);
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks for error conditions for R6 (RCA) response.
+ * @param hsd: SD handle
+ * @param SD_CMD: The sent command index
+ * @param pRCA: Pointer to the variable that will contain the SD card relative
+ * address RCA
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_CmdResp6Error(SD_HandleTypeDef *hsd, uint8_t SD_CMD, uint16_t *pRCA)
+{
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t response_r1;
+
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT))
+ {
+ }
+
+ if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CTIMEOUT))
+ {
+ errorstate = SD_CMD_RSP_TIMEOUT;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ return errorstate;
+ }
+ else if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL))
+ {
+ errorstate = SD_CMD_CRC_FAIL;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CCRCFAIL);
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Check response received is of desired command */
+ if(SDMMC_GetCommandResponse(hsd->Instance) != SD_CMD)
+ {
+ errorstate = SD_ILLEGAL_CMD;
+
+ return errorstate;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ /* We have received response, retrieve it. */
+ response_r1 = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ if((response_r1 & (SD_R6_GENERAL_UNKNOWN_ERROR | SD_R6_ILLEGAL_CMD | SD_R6_COM_CRC_FAILED)) == SD_ALLZERO)
+ {
+ *pRCA = (uint16_t) (response_r1 >> 16);
+
+ return errorstate;
+ }
+
+ if((response_r1 & SD_R6_GENERAL_UNKNOWN_ERROR) == SD_R6_GENERAL_UNKNOWN_ERROR)
+ {
+ return(SD_GENERAL_UNKNOWN_ERROR);
+ }
+
+ if((response_r1 & SD_R6_ILLEGAL_CMD) == SD_R6_ILLEGAL_CMD)
+ {
+ return(SD_ILLEGAL_CMD);
+ }
+
+ if((response_r1 & SD_R6_COM_CRC_FAILED) == SD_R6_COM_CRC_FAILED)
+ {
+ return(SD_COM_CRC_FAILED);
+ }
+
+ return errorstate;
+}
+
+/**
+ * @brief Enables the SDMMC wide bus mode.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_WideBus_Enable(SD_HandleTypeDef *hsd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ uint32_t scr[2] = {0, 0};
+
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SD_CARD_LOCKED) == SD_CARD_LOCKED)
+ {
+ errorstate = SD_LOCK_UNLOCK_FAILED;
+
+ return errorstate;
+ }
+
+ /* Get SCR Register */
+ errorstate = SD_FindSCR(hsd, scr);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* If requested card supports wide bus operation */
+ if((scr[1] & SD_WIDE_BUS_SUPPORT) != SD_ALLZERO)
+ {
+ /* Send CMD55 APP_CMD with argument as card's RCA.*/
+ sdmmc_cmdinitstructure.Argument = (uint32_t)(hsd->RCA << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_CMD);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
+ sdmmc_cmdinitstructure.Argument = 2;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_SD_SET_BUSWIDTH);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ return errorstate;
+ }
+ else
+ {
+ errorstate = SD_REQUEST_NOT_APPLICABLE;
+
+ return errorstate;
+ }
+}
+
+/**
+ * @brief Disables the SDMMC wide bus mode.
+ * @param hsd: SD handle
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_WideBus_Disable(SD_HandleTypeDef *hsd)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+
+ uint32_t scr[2] = {0, 0};
+
+ if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SD_CARD_LOCKED) == SD_CARD_LOCKED)
+ {
+ errorstate = SD_LOCK_UNLOCK_FAILED;
+
+ return errorstate;
+ }
+
+ /* Get SCR Register */
+ errorstate = SD_FindSCR(hsd, scr);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* If requested card supports 1 bit mode operation */
+ if((scr[1] & SD_SINGLE_BUS_SUPPORT) != SD_ALLZERO)
+ {
+ /* Send CMD55 APP_CMD with argument as card's RCA */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)(hsd->RCA << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_CMD);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Send ACMD6 APP_CMD with argument as 0 for single bus mode */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_SD_SET_BUSWIDTH);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ return errorstate;
+ }
+ else
+ {
+ errorstate = SD_REQUEST_NOT_APPLICABLE;
+
+ return errorstate;
+ }
+}
+
+
+/**
+ * @brief Finds the SD card SCR register value.
+ * @param hsd: SD handle
+ * @param pSCR: pointer to the buffer that will contain the SCR value
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ SDMMC_DataInitTypeDef sdmmc_datainitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ uint32_t index = 0;
+ uint32_t tempscr[2] = {0, 0};
+
+ /* Set Block Size To 8 Bytes */
+ /* Send CMD55 APP_CMD with argument as card's RCA */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)8;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SET_BLOCKLEN);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ /* Send CMD55 APP_CMD with argument as card's RCA */
+ sdmmc_cmdinitstructure.Argument = (uint32_t)((hsd->RCA) << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_APP_CMD);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
+ sdmmc_datainitstructure.DataLength = 8;
+ sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_8B;
+ sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
+ sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
+ sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
+ SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);
+
+ /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
+ sdmmc_cmdinitstructure.Argument = 0;
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_APP_SEND_SCR;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ /* Check for error conditions */
+ errorstate = SD_CmdResp1Error(hsd, SD_CMD_SD_APP_SEND_SCR);
+
+ if(errorstate != SD_OK)
+ {
+ return errorstate;
+ }
+
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
+ {
+ if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL))
+ {
+ *(tempscr + index) = SDMMC_ReadFIFO(hsd->Instance);
+ index++;
+ }
+ }
+
+ if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DTIMEOUT);
+
+ errorstate = SD_DATA_TIMEOUT;
+
+ return errorstate;
+ }
+ else if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_DCRCFAIL);
+
+ errorstate = SD_DATA_CRC_FAIL;
+
+ return errorstate;
+ }
+ else if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
+ {
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_RXOVERR);
+
+ errorstate = SD_RX_OVERRUN;
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+ *(pSCR + 1) = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) |\
+ ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24);
+
+ *(pSCR) = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) |\
+ ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24);
+
+ return errorstate;
+}
+
+/**
+ * @brief Checks if the SD card is in programming state.
+ * @param hsd: SD handle
+ * @param pStatus: pointer to the variable that will contain the SD card state
+ * @retval SD Card error state
+ */
+static HAL_SD_ErrorTypedef SD_IsCardProgramming(SD_HandleTypeDef *hsd, uint8_t *pStatus)
+{
+ SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure;
+ HAL_SD_ErrorTypedef errorstate = SD_OK;
+ __IO uint32_t responseR1 = 0;
+
+ sdmmc_cmdinitstructure.Argument = (uint32_t)(hsd->RCA << 16);
+ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEND_STATUS;
+ sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT;
+ sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO;
+ sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE;
+ SDMMC_SendCommand(hsd->Instance, &sdmmc_cmdinitstructure);
+
+ while(!__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT))
+ {
+ }
+
+ if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CTIMEOUT))
+ {
+ errorstate = SD_CMD_RSP_TIMEOUT;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CTIMEOUT);
+
+ return errorstate;
+ }
+ else if(__HAL_SD_SDMMC_GET_FLAG(hsd, SDMMC_FLAG_CCRCFAIL))
+ {
+ errorstate = SD_CMD_CRC_FAIL;
+
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_FLAG_CCRCFAIL);
+
+ return errorstate;
+ }
+ else
+ {
+ /* No error flag set */
+ }
+
+ /* Check response received is of desired command */
+ if((uint32_t)SDMMC_GetCommandResponse(hsd->Instance) != SD_CMD_SEND_STATUS)
+ {
+ errorstate = SD_ILLEGAL_CMD;
+
+ return errorstate;
+ }
+
+ /* Clear all the static flags */
+ __HAL_SD_SDMMC_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
+
+
+ /* We have received response, retrieve it for analysis */
+ responseR1 = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);
+
+ /* Find out card status */
+ *pStatus = (uint8_t)((responseR1 >> 9) & 0x0000000F);
+
+ if((responseR1 & SD_OCR_ERRORBITS) == SD_ALLZERO)
+ {
+ return errorstate;
+ }
+
+ if((responseR1 & SD_OCR_ADDR_OUT_OF_RANGE) == SD_OCR_ADDR_OUT_OF_RANGE)
+ {
+ return(SD_ADDR_OUT_OF_RANGE);
+ }
+
+ if((responseR1 & SD_OCR_ADDR_MISALIGNED) == SD_OCR_ADDR_MISALIGNED)
+ {
+ return(SD_ADDR_MISALIGNED);
+ }
+
+ if((responseR1 & SD_OCR_BLOCK_LEN_ERR) == SD_OCR_BLOCK_LEN_ERR)
+ {
+ return(SD_BLOCK_LEN_ERR);
+ }
+
+ if((responseR1 & SD_OCR_ERASE_SEQ_ERR) == SD_OCR_ERASE_SEQ_ERR)
+ {
+ return(SD_ERASE_SEQ_ERR);
+ }
+
+ if((responseR1 & SD_OCR_BAD_ERASE_PARAM) == SD_OCR_BAD_ERASE_PARAM)
+ {
+ return(SD_BAD_ERASE_PARAM);
+ }
+
+ if((responseR1 & SD_OCR_WRITE_PROT_VIOLATION) == SD_OCR_WRITE_PROT_VIOLATION)
+ {
+ return(SD_WRITE_PROT_VIOLATION);
+ }
+
+ if((responseR1 & SD_OCR_LOCK_UNLOCK_FAILED) == SD_OCR_LOCK_UNLOCK_FAILED)
+ {
+ return(SD_LOCK_UNLOCK_FAILED);
+ }
+
+ if((responseR1 & SD_OCR_COM_CRC_FAILED) == SD_OCR_COM_CRC_FAILED)
+ {
+ return(SD_COM_CRC_FAILED);
+ }
+
+ if((responseR1 & SD_OCR_ILLEGAL_CMD) == SD_OCR_ILLEGAL_CMD)
+ {
+ return(SD_ILLEGAL_CMD);
+ }
+
+ if((responseR1 & SD_OCR_CARD_ECC_FAILED) == SD_OCR_CARD_ECC_FAILED)
+ {
+ return(SD_CARD_ECC_FAILED);
+ }
+
+ if((responseR1 & SD_OCR_CC_ERROR) == SD_OCR_CC_ERROR)
+ {
+ return(SD_CC_ERROR);
+ }
+
+ if((responseR1 & SD_OCR_GENERAL_UNKNOWN_ERROR) == SD_OCR_GENERAL_UNKNOWN_ERROR)
+ {
+ return(SD_GENERAL_UNKNOWN_ERROR);
+ }
+
+ if((responseR1 & SD_OCR_STREAM_READ_UNDERRUN) == SD_OCR_STREAM_READ_UNDERRUN)
+ {
+ return(SD_STREAM_READ_UNDERRUN);
+ }
+
+ if((responseR1 & SD_OCR_STREAM_WRITE_OVERRUN) == SD_OCR_STREAM_WRITE_OVERRUN)
+ {
+ return(SD_STREAM_WRITE_OVERRUN);
+ }
+
+ if((responseR1 & SD_OCR_CID_CSD_OVERWRITE) == SD_OCR_CID_CSD_OVERWRITE)
+ {
+ return(SD_CID_CSD_OVERWRITE);
+ }
+
+ if((responseR1 & SD_OCR_WP_ERASE_SKIP) == SD_OCR_WP_ERASE_SKIP)
+ {
+ return(SD_WP_ERASE_SKIP);
+ }
+
+ if((responseR1 & SD_OCR_CARD_ECC_DISABLED) == SD_OCR_CARD_ECC_DISABLED)
+ {
+ return(SD_CARD_ECC_DISABLED);
+ }
+
+ if((responseR1 & SD_OCR_ERASE_RESET) == SD_OCR_ERASE_RESET)
+ {
+ return(SD_ERASE_RESET);
+ }
+
+ if((responseR1 & SD_OCR_AKE_SEQ_ERROR) == SD_OCR_AKE_SEQ_ERROR)
+ {
+ return(SD_AKE_SEQ_ERROR);
+ }
+
+ return errorstate;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SD_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_spi.c b/stmhal/hal/l4/src/stm32l4xx_hal_spi.c
new file mode 100644
index 000000000..828b7e0ee
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_spi.c
@@ -0,0 +1,2769 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_spi.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief SPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Serial Peripheral Interface (SPI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The SPI HAL driver can be used as follows:
+
+ (#) Declare a SPI_HandleTypeDef handle structure, for example:
+ SPI_HandleTypeDef hspi;
+
+ (#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API:
+ (##) Enable the SPIx interface clock
+ (##) SPI pins configuration
+ (+++) Enable the clock for the SPI GPIOs
+ (+++) Configure these SPI pins as alternate function push-pull
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the SPIx interrupt priority
+ (+++) Enable the NVIC SPI IRQ handle
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel
+ (+++) Enable the DMAx clock
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx channel
+ (+++) Associate the initialized hdma_tx handle to the hspi DMA Tx or Rx handle
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx or Rx channel
+
+ (#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS
+ management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure.
+
+ (#) Initialize the SPI registers by calling the HAL_SPI_Init() API:
+ (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+ by calling the customized HAL_SPI_MspInit() API.
+ [..]
+ Circular mode restriction:
+ (#) The DMA circular mode cannot be used when the SPI is configured in these modes:
+ (##) Master 2Lines RxOnly
+ (##) Master 1Line Rx
+ (#) The CRC feature is not managed when the DMA circular mode is enabled
+ (#) When the SPI DMA Pause/Stop features are used, we must use the following APIs
+ the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPI SPI
+ * @brief SPI HAL module driver
+ * @{
+ */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPI_Private_Constants SPI Private Constants
+ * @{
+ */
+#define SPI_DEFAULT_TIMEOUT 50
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup SPI_Private_Functions SPI Private Functions
+ * @{
+ */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAError(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, uint32_t State, uint32_t Timeout);
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State, uint32_t Timeout);
+static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi);
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout);
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup SPI_Exported_Functions SPI Exported Functions
+ * @{
+ */
+
+/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ de-initialize the SPIx peripheral:
+
+ (+) User must implement HAL_SPI_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_SPI_Init() to configure the selected device with
+ the selected configuration:
+ (++) Mode
+ (++) Direction
+ (++) Data Size
+ (++) Clock Polarity and Phase
+ (++) NSS Management
+ (++) BaudRate Prescaler
+ (++) FirstBit
+ (++) TIMode
+ (++) CRC Calculation
+ (++) CRC Polynomial if CRC enabled
+ (++) CRC Length, used only with Data8 and Data16
+ (++) FIFO reception threshold
+
+ (+) Call the function HAL_SPI_DeInit() to restore the default configuration
+ of the selected SPIx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the SPI according to the specified parameters
+ * in the SPI_InitTypeDef and initialize the associated handle.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
+{
+ uint32_t frxth;
+
+ /* Check the SPI handle allocation */
+ if(hspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+ assert_param(IS_SPI_MODE(hspi->Init.Mode));
+ assert_param(IS_SPI_DIRECTION(hspi->Init.Direction));
+ assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize));
+ assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity));
+ assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase));
+ assert_param(IS_SPI_NSS(hspi->Init.NSS));
+ assert_param(IS_SPI_NSSP(hspi->Init.NSSPMode));
+ assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+ assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit));
+ assert_param(IS_SPI_TIMODE(hspi->Init.TIMode));
+ assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation));
+ assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
+ assert_param(IS_SPI_CRC_LENGTH(hspi->Init.CRCLength));
+
+ if(hspi->State == HAL_SPI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hspi->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_SPI_MspInit(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY;
+
+ /* Disable the selected SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* Align by default the rs fifo threshold on the data size */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ frxth = SPI_RXFIFO_THRESHOLD_HF;
+ }
+ else
+ {
+ frxth = SPI_RXFIFO_THRESHOLD_QF;
+ }
+
+ /* CRC calculation is valid only for 16Bit and 8 Bit */
+ if(( hspi->Init.DataSize != SPI_DATASIZE_16BIT ) && ( hspi->Init.DataSize != SPI_DATASIZE_8BIT ))
+ {
+ /* CRC must be disabled */
+ hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ }
+
+ /* Align the CRC Length on the data size */
+ if( hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
+ {
+ /* CRC Length aligned on the data size : value set by default */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
+ }
+ else
+ {
+ hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
+ }
+ }
+
+ /*---------------------------- SPIx CR1 & CR2 Configuration ------------------------*/
+ /* Configure : SPI Mode, Communication Mode, Clock polarity and phase, NSS management,
+ Communication speed, First bit, CRC calculation state, CRC Length */
+ hspi->Instance->CR1 = (hspi->Init.Mode | hspi->Init.Direction |
+ hspi->Init.CLKPolarity | hspi->Init.CLKPhase | (hspi->Init.NSS & SPI_CR1_SSM) |
+ hspi->Init.BaudRatePrescaler | hspi->Init.FirstBit | hspi->Init.CRCCalculation);
+
+ if( hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ {
+ hspi->Instance->CR1|= SPI_CR1_CRCL;
+ }
+
+ /* Configure : NSS management */
+ /* Configure : Rx Fifo Threshold */
+ hspi->Instance->CR2 = (((hspi->Init.NSS >> 16) & SPI_CR2_SSOE) | hspi->Init.TIMode | hspi->Init.NSSPMode |
+ hspi->Init.DataSize ) | frxth;
+
+ /*---------------------------- SPIx CRCPOLY Configuration --------------------*/
+ /* Configure : CRC Polynomial */
+ hspi->Instance->CRCPR = hspi->Init.CRCPolynomial;
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->State= HAL_SPI_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the SPI peripheral.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
+{
+ /* Check the SPI handle allocation */
+ if(hspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+ hspi->State = HAL_SPI_STATE_BUSY;
+
+ /* Disable the SPI Peripheral Clock */
+ __HAL_SPI_DISABLE(hspi);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_SPI_MspDeInit(hspi);
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->State = HAL_SPI_STATE_RESET;
+
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the SPI MSP.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspInit should be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the SPI MSP.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspDeInit should be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Exported_Functions_Group2 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SPI
+ data transfers.
+
+ [..] The SPI supports master and slave mode :
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode: The communication is performed using Interrupts
+ or DMA, These APIs return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected
+
+ (#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA)
+ exist for 1Line (simplex) and 2Lines (full duplex) modes.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size: amount of data to be sent
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pData == NULL ) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ /* Set the transaction information */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ hspi->RxXferSize = 0;
+ hspi->RxXferCount = 0;
+
+ /* Configure communication direction : 1Line */
+ if(hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_TX(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Transmit data in 16 Bit mode */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* Transmit data in 16 Bit mode */
+ while (hspi->TxXferCount > 0)
+ {
+ /* Wait until TXE flag is set to send data */
+ if((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE)
+ {
+ hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if((Timeout == 0) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout)))
+ {
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ }
+ }
+ }
+ /* Transmit data in 8 Bit mode */
+ else
+ {
+ while (hspi->TxXferCount > 0)
+ {
+ /* Wait until TXE flag is set to send data */
+ if((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE)
+ {
+ if(hspi->TxXferCount > 1)
+ {
+ /* write on the data register in packing mode */
+ hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2;
+ }
+ else
+ {
+ *((__IO uint8_t*)&hspi->Instance->DR) = (*hspi->pTxBuffPtr++);
+ hspi->TxXferCount--;
+ }
+ }
+ else
+ {
+ /* Timeout management */
+ if((Timeout == 0) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout)))
+ {
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ }
+ }
+ }
+
+ /* Enable CRC Transmission */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->Instance->CR1|= SPI_CR1_CRCNEXT;
+ }
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Clear overrun flag in 2 Lines communication mode because received is not read */
+ if(hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ errorcode = HAL_ERROR;
+ }
+
+error:
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size: amount of data to be received
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ __IO uint16_t tmpreg;
+ uint32_t tickstart = HAL_GetTick();
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ if((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ {
+ /* the receive process is not supported in 2Lines direction master mode */
+ /* in this case we call the TransmitReceive process */
+ /* Process Locked */
+ return HAL_SPI_TransmitReceive(hspi,pData,pData,Size,Timeout);
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pData == NULL ) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+ hspi->pTxBuffPtr = (uint8_t *)NULL;
+ hspi->TxXferSize = 0;
+ hspi->TxXferCount = 0;
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ /* this is done to handle the CRCNEXT before the latest data */
+ hspi->RxXferCount--;
+ }
+
+ /* Set the Rx Fido threshold */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* set fiforxthresold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* set fiforxthresold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+ /* Configure communication direction 1Line and enabled SPI if needed */
+ if(hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ if(hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+ {
+ /* Transfer loop */
+ while(hspi->RxXferCount > 0)
+ {
+ /* Check the RXNE flag */
+ if((hspi->Instance->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE)
+ {
+ /* read the received data */
+ (*hspi->pRxBuffPtr++)= *(__IO uint8_t *)&hspi->Instance->DR;
+ hspi->RxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if((Timeout == 0) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout)))
+ {
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Transfer loop */
+ while(hspi->RxXferCount > 0)
+ {
+ /* Check the RXNE flag */
+ if((hspi->Instance->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE)
+ {
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ }
+ else
+ {
+ /* Timeout management */
+ if((Timeout == 0) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout)))
+ {
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ }
+ }
+ }
+
+ /* Handle the CRC Transmission */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* freeze the CRC before the latest data */
+ hspi->Instance->CR1|= SPI_CR1_CRCNEXT;
+
+ /* Read the latest data */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ /* the latest data has not been received */
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+
+ /* Receive last data in 16 Bit mode */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ }
+ /* Receive last data in 8 Bit mode */
+ else
+ {
+ *hspi->pRxBuffPtr = *(__IO uint8_t *)&hspi->Instance->DR;
+ }
+
+ /* Wait until TXE flag */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ /* Flag Error*/
+ hspi->ErrorCode = HAL_SPI_ERROR_CRC;
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+
+ if(hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+ {
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ else
+ {
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ if((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ {
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode = HAL_SPI_ERROR_CRC;
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ }
+ }
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTransaction(hspi,Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Check if CRC error occurred */
+ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ errorcode = HAL_ERROR;
+ }
+
+error :
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in blocking mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @param Size: amount of data to be sent and received
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
+{
+__IO uint16_t tmpreg;
+ uint32_t tickstart = HAL_GetTick();
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = pRxData;
+ hspi->RxXferCount = Size;
+ hspi->RxXferSize = Size;
+ hspi->pTxBuffPtr = pTxData;
+ hspi->TxXferCount = Size;
+ hspi->TxXferSize = Size;
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* Set the Rx Fido threshold */
+ if((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1))
+ {
+ /* set fiforxthreshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* set fiforxthreshold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Transmit and Receive data in 16 Bit mode */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ while ((hspi->TxXferCount > 0 ) || (hspi->RxXferCount > 0))
+ {
+ /* Check TXE flag */
+ if((hspi->TxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE))
+ {
+ hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+ /* Enable CRC Transmission */
+ if((hspi->TxXferCount == 0) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ hspi->Instance->CR1|= SPI_CR1_CRCNEXT;
+ }
+ }
+
+ /* Check RXNE flag */
+ if((hspi->RxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE))
+ {
+ *((uint16_t *)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ }
+ if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout))
+ {
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ }
+ }
+ /* Transmit and Receive data in 8 Bit mode */
+ else
+ {
+ while((hspi->TxXferCount > 0) || (hspi->RxXferCount > 0))
+ {
+ /* check TXE flag */
+ if((hspi->TxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE))
+ {
+ if(hspi->TxXferCount > 1)
+ {
+ hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2;
+ }
+ else
+ {
+ *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr++);
+ hspi->TxXferCount--;
+ }
+
+ /* Enable CRC Transmission */
+ if((hspi->TxXferCount == 0) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+ }
+
+ /* Wait until RXNE flag is reset */
+ if((hspi->RxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE))
+ {
+ if(hspi->RxXferCount > 1)
+ {
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount -= 2;
+ if(hspi->RxXferCount <= 1)
+ {
+ /* set fiforxthresold before to switch on 8 bit data size */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ }
+ else
+ {
+ (*hspi->pRxBuffPtr++) = *(__IO uint8_t *)&hspi->Instance->DR;
+ hspi->RxXferCount--;
+ }
+ }
+ if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout))
+ {
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ }
+ }
+
+ /* Read CRC from DR to close CRC calculation process */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Wait until TXE flag */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+
+ if(hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+ {
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ else
+ {
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ if(hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ {
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ errorcode = HAL_TIMEOUT;
+ goto error;
+ }
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ }
+ }
+
+ /* Check if CRC error occurred */
+ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ /* Clear CRC Flag */
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+
+ errorcode = HAL_ERROR;
+ }
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ errorcode = HAL_ERROR;
+ }
+
+error :
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size: amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if((pData == NULL) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ /* prepare the transfer */
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ hspi->RxXferSize = 0;
+ hspi->RxXferCount = 0;
+ hspi->RxISR = NULL;
+
+ /* Set the function for IT treatment */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
+ {
+ hspi->TxISR = SPI_TxISR_16BIT;
+ }
+ else
+ {
+ hspi->TxISR = SPI_TxISR_8BIT;
+ }
+
+ /* Configure communication direction : 1Line */
+ if(hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_TX(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* Enable TXE and ERR interrupt */
+ __HAL_SPI_ENABLE_IT(hspi,(SPI_IT_TXE));
+
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+error :
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size: amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+ if((pData == NULL) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ /* Configure communication */
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+ hspi->pTxBuffPtr = (uint8_t *)NULL;
+ hspi->TxXferSize = 0;
+ hspi->TxXferCount = 0;
+
+ if((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ /* the receive process is not supported in 2Lines direction master mode */
+ /* in this we call the TransmitReceive process */
+ return HAL_SPI_TransmitReceive_IT(hspi,pData,pData,Size);
+ }
+
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->CRCSize = 1;
+ if((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ {
+ hspi->CRCSize = 2;
+ }
+ }
+ else
+ {
+ hspi->CRCSize = 0;
+ }
+
+ hspi->TxISR = NULL;
+ /* check the data size to adapt Rx threshold and the set the function for IT treatment */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
+ {
+ /* set fiforxthresold according the reception data length: 16 bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_RxISR_16BIT;
+ }
+ else
+ {
+ /* set fiforxthresold according the reception data length: 8 bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_RxISR_8BIT;
+ }
+
+ /* Configure communication direction : 1Line */
+ if(hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* Enable TXE and ERR interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+error :
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @param Size: amount of data to be sent and received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ if(!((hspi->State == HAL_SPI_STATE_READY) || \
+ ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->State == HAL_SPI_STATE_BUSY_RX))))
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ hspi->CRCSize = 0;
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->CRCSize = 1;
+ if((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+ {
+ hspi->CRCSize = 2;
+ }
+ }
+
+ if(hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = pTxData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = pRxData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Set the function for IT treatment */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
+ {
+ hspi->RxISR = SPI_2linesRxISR_16BIT;
+ hspi->TxISR = SPI_2linesTxISR_16BIT;
+ }
+ else
+ {
+ hspi->RxISR = SPI_2linesRxISR_8BIT;
+ hspi->TxISR = SPI_2linesTxISR_8BIT;
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* check if packing mode is enabled and if there is more than 2 data to receive */
+ if((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount >= 2))
+ {
+ /* set fiforxthresold according the reception data length: 16 bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* set fiforxthresold according the reception data length: 8 bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+ /* Enable TXE, RXNE and ERR interrupt */
+ __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+error :
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @param Size: amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pData == NULL) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)NULL;
+ hspi->RxXferSize = 0;
+ hspi->RxXferCount = 0;
+
+ /* Configure communication direction : 1Line */
+ if(hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_TX(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* Set the SPI TxDMA Half transfer complete callback */
+ hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt;
+
+ /* Set the SPI TxDMA transfer complete callback */
+ hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt;
+
+ /* Set the DMA error callback */
+ hspi->hdmatx->XferErrorCallback = SPI_DMAError;
+
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ /* packing mode is enabled only if the DMA setting is HALWORD */
+ if((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD))
+ {
+ /* Check the even/odd of the data size + crc if enabled */
+ if((hspi->TxXferCount & 0x1) == 0)
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = (hspi->TxXferCount >> 1);
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = (hspi->TxXferCount >> 1) + 1;
+ }
+ }
+
+ /* Enable the Tx DMA channel */
+ HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount);
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Enable Tx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+error :
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @note When the CRC feature is enabled the pData Length must be Size + 1.
+ * @param Size: amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pData == NULL) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ hspi->State = HAL_SPI_STATE_BUSY_RX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pRxBuffPtr = pData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+ hspi->pTxBuffPtr = (uint8_t *)NULL;
+ hspi->TxXferSize = 0;
+ hspi->TxXferCount = 0;
+
+ if((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ /* the receive process is not supported in 2Lines direction master mode */
+ /* in this case we call the TransmitReceive process */
+ return HAL_SPI_TransmitReceive_DMA(hspi,pData,pData,Size);
+ }
+
+ /* Configure communication direction : 1Line */
+ if(hspi->Init.Direction == SPI_DIRECTION_1LINE)
+ {
+ SPI_1LINE_RX(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* packing mode management is enabled by the DMA settings */
+ if((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD))
+ {
+ /* Restriction the DMA data received is not allowed in this mode */
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ if( hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* set fiforxthresold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* set fiforxthresold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+
+ /* Set the SPI RxDMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+
+ /* Set the SPI Rx DMA transfer complete callback */
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Enable Rx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ /* Enable the Rx DMA channel */
+ HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount);
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+error:
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in non-blocking mode with DMA.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @param pRxData: pointer to reception data buffer
+ * @note When the CRC feature is enabled the pRxData Length must be Size + 1
+ * @param Size: amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
+{
+ HAL_StatusTypeDef errorcode = HAL_OK;
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ if(!((hspi->State == HAL_SPI_STATE_READY) ||
+ ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->State == HAL_SPI_STATE_BUSY_RX))))
+ {
+ errorcode = HAL_BUSY;
+ goto error;
+ }
+
+ if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0))
+ {
+ errorcode = HAL_ERROR;
+ goto error;
+ }
+
+ /* check if the transmit Receive function is not called by a receive master */
+ if(hspi->State != HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+ }
+
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = (uint8_t *)pTxData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = (uint8_t *)pRxData;
+ hspi->RxXferSize = Size;
+ hspi->RxXferCount = Size;
+
+ /* Reset CRC Calculation + increase the rxsize */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ /* Reset the threshold bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX | SPI_CR2_LDMARX);
+
+ /* the packing mode management is enabled by the DMA settings according the spi data size */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ /* set fiforxthreshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* set fiforxthresold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ if(hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ if((hspi->TxXferSize & 0x1) == 0x0)
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = hspi->TxXferCount >> 1;
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+ hspi->TxXferCount = (hspi->TxXferCount >> 1) + 1;
+ }
+ }
+
+ if(hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ /* set fiforxthresold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ if((hspi->RxXferCount & 0x1) == 0x0 )
+ {
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ hspi->RxXferCount = hspi->RxXferCount >> 1;
+ }
+ else
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ hspi->RxXferCount = (hspi->RxXferCount >> 1) + 1;
+ }
+ }
+ }
+
+ /* Set the SPI Rx DMA transfer complete callback if the transfer request is a
+ reception request (RXNE) */
+ if(hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ /* Set the SPI Rx DMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+ }
+ else
+ {
+ /* Set the SPI Rx DMA Half transfer complete callback */
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
+ }
+
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Enable Rx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ /* Enable the Rx DMA channel */
+ HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t) hspi->pRxBuffPtr, hspi->RxXferCount);
+
+ /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
+ is performed in DMA reception complete callback */
+ hspi->hdmatx->XferHalfCpltCallback = NULL;
+ hspi->hdmatx->XferCpltCallback = NULL;
+
+ /* Set the DMA error callback */
+ hspi->hdmatx->XferErrorCallback = SPI_DMAError;
+
+ /* Enable the Tx DMA channel */
+ HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount);
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ /* Enable Tx DMA Request */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+error :
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return errorcode;
+}
+
+/**
+ * @brief Pause the DMA Transfer.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
+{
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Disable the SPI DMA Tx & Rx requests */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
+{
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* Enable the SPI DMA Tx & Rx requests */
+ SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
+{
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or HAL_SPI_TxRxCpltCallback():
+ when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
+ and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or HAL_SPI_TxRxCpltCallback()
+ */
+
+ /* Abort the SPI DMA tx channel */
+ if(hspi->hdmatx != NULL)
+ {
+ HAL_DMA_Abort(hspi->hdmatx);
+ }
+ /* Abort the SPI DMA rx channel */
+ if(hspi->hdmarx != NULL)
+ {
+ HAL_DMA_Abort(hspi->hdmarx);
+ }
+
+ /* Disable the SPI DMA Tx & Rx requests */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+ hspi->State = HAL_SPI_STATE_READY;
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle SPI interrupt request.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval None
+ */
+void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
+{
+ uint32_t itsource = hspi->Instance->CR2;
+ uint32_t itflag = hspi->Instance->SR;
+
+ /* SPI in mode Receiver ----------------------------------------------------*/
+ if(((itflag & SPI_FLAG_OVR) == RESET) &&
+ ((itflag & SPI_FLAG_RXNE) != RESET) && ((itsource & SPI_IT_RXNE) != RESET))
+ {
+ hspi->RxISR(hspi);
+ return;
+ }
+
+ /* SPI in mode Transmitter ---------------------------------------------------*/
+ if(((itflag & SPI_FLAG_TXE) != RESET) && ((itsource & SPI_IT_TXE) != RESET))
+ {
+ hspi->TxISR(hspi);
+ return;
+ }
+
+ /* SPI in Error Treatment ---------------------------------------------------*/
+ if((itflag & (SPI_FLAG_MODF | SPI_FLAG_OVR | SPI_FLAG_FRE)) != RESET)
+ {
+ /* SPI Overrun error interrupt occurred -------------------------------------*/
+ if((itflag & SPI_FLAG_OVR) != RESET)
+ {
+ if(hspi->State != HAL_SPI_STATE_BUSY_TX)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_OVR;
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ /* SPI Mode Fault error interrupt occurred -------------------------------------*/
+ if((itflag & SPI_FLAG_MODF) != RESET)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_MODF;
+ __HAL_SPI_CLEAR_MODFFLAG(hspi);
+ }
+
+ /* SPI Frame error interrupt occurred ----------------------------------------*/
+ if((itflag & SPI_FLAG_FRE) != RESET)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FRE;
+ __HAL_SPI_CLEAR_FREFLAG(hspi);
+ }
+
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
+ hspi->State = HAL_SPI_STATE_READY;
+ HAL_SPI_ErrorCallback(hspi);
+ return;
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_RxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx and Rx Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxRxCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxHalfCpltCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx and Rx Half Transfer callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file
+ */
+}
+
+/**
+ * @brief SPI error callback.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_ErrorCallback should be implemented in the user file
+ */
+ /* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes
+ and user can use HAL_SPI_GetError() API to check the latest error occurred
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief SPI control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SPI.
+ (+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral
+ (+) HAL_SPI_GetError() check in run-time Errors occurring during communication
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the SPI handle state.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval SPI state
+ */
+HAL_SPI_StateTypeDef HAL_SPI_GetState(SPI_HandleTypeDef *hspi)
+{
+ /* Return SPI handle state */
+ return hspi->State;
+}
+
+/**
+ * @brief Return the SPI error code.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval SPI error code in bitmap format
+ */
+uint32_t HAL_SPI_GetError(SPI_HandleTypeDef *hspi)
+{
+ return hspi->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup SPI_Private_Functions
+ * @brief Private functions
+ * @{
+ */
+
+/**
+ * @brief DMA SPI transmit process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ if((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+ {
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,SPI_DEFAULT_TIMEOUT) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Clear overrun flag in 2 Lines communication mode because received data is not read */
+ if(hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ hspi->TxXferCount = 0;
+ hspi->State = HAL_SPI_STATE_READY;
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_ErrorCallback(hspi);
+ return;
+ }
+ }
+ HAL_SPI_TxCpltCallback(hspi);
+}
+
+/**
+ * @brief DMA SPI receive process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ if((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+ {
+ __IO uint16_t tmpreg;
+
+ /* CRC handling */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Wait until TXE flag */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, SPI_DEFAULT_TIMEOUT) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ }
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ else
+ {
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ if(hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+ {
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, SPI_DEFAULT_TIMEOUT) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ }
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ }
+ }
+
+ /* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTransaction(hspi,SPI_DEFAULT_TIMEOUT)!=HAL_OK)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_FLAG;
+ }
+
+ hspi->RxXferCount = 0;
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Check if CRC error occurred */
+ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_ErrorCallback(hspi);
+ return;
+ }
+ }
+ HAL_SPI_RxCpltCallback(hspi);
+}
+
+/**
+ * @brief DMA SPI transmit receive process complete callback.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ if((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+ {
+ __IO int16_t tmpreg;
+ /* CRC handling */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ if((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_8BIT))
+ {
+ if(SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_QUARTER_FULL, SPI_DEFAULT_TIMEOUT) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ }
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ else
+ {
+ if(SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_HALF_FULL, SPI_DEFAULT_TIMEOUT) != HAL_OK)
+ {
+ /* Error on the CRC reception */
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ }
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ }
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,SPI_DEFAULT_TIMEOUT) != HAL_OK)
+ {
+ hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Disable Rx/Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ hspi->TxXferCount = 0;
+ hspi->RxXferCount = 0;
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Check if CRC error occurred */
+ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ }
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_ErrorCallback(hspi);
+ return;
+ }
+ }
+ HAL_SPI_TxRxCpltCallback(hspi);
+}
+
+/**
+ * @brief DMA SPI half transmit process complete callback.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ HAL_SPI_TxHalfCpltCallback(hspi);
+}
+
+/**
+ * @brief DMA SPI half receive process complete callback.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ HAL_SPI_RxHalfCpltCallback(hspi);
+}
+
+/**
+ * @brief DMA SPI half transmit receive process complete callback.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ HAL_SPI_TxRxHalfCpltCallback(hspi);
+}
+
+/**
+ * @brief DMA SPI communication error callback.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SPI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Stop the disable DMA transfer on SPI side */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+ hspi->ErrorCode|= HAL_SPI_ERROR_DMA;
+ hspi->State = HAL_SPI_STATE_READY;
+ HAL_SPI_ErrorCallback(hspi);
+}
+
+/**
+ * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in packing mode */
+ if(hspi->RxXferCount > 1)
+ {
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount -= 2;
+ if(hspi->RxXferCount == 1)
+ {
+ /* set fiforxthresold according the reception data length: 8bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ }
+ /* Receive data in 8 Bit mode */
+ else
+ {
+ *hspi->pRxBuffPtr++ = *((__IO uint8_t *)&hspi->Instance->DR);
+ hspi->RxXferCount--;
+ }
+
+ /* check end of the reception */
+ if(hspi->RxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_2linesRxISR_8BITCRC;
+ return;
+ }
+
+ /* Disable RXNE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+ if(hspi->TxXferCount == 0)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint8_t tmpreg = *((__IO uint8_t *)&hspi->Instance->DR);
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ hspi->CRCSize--;
+
+ /* check end of the reception */
+ if(hspi->CRCSize == 0)
+ {
+ /* Disable RXNE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+ if(hspi->TxXferCount == 0)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Tx 8-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in packing Bit mode */
+ if(hspi->TxXferCount >= 2)
+ {
+ hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2;
+ }
+ /* Transmit data in 8 Bit mode */
+ else
+ {
+ *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr++);
+ hspi->TxXferCount--;
+ }
+
+ /* check the end of the transmission */
+ if(hspi->TxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+ /* Disable TXE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+
+ if(hspi->RxXferCount == 0)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Rx 16-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in 16 Bit mode */
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+
+ if(hspi->RxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->RxISR = SPI_2linesRxISR_16BITCRC;
+ return;
+ }
+
+ /* Disable RXNE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+ if(hspi->TxXferCount == 0)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Receive data in 16 Bit mode */
+ __IO uint16_t tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ /* Disable RXNE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+ SPI_CloseRxTx_ISR(hspi);
+}
+
+/**
+ * @brief Tx 16-bit handler for Transmit and Receive in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 16 Bit mode */
+ hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+ /* Enable CRC Transmission */
+ if(hspi->TxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+ /* Disable TXE interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+
+ if(hspi->RxXferCount == 0)
+ {
+ SPI_CloseRxTx_ISR(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Manage the CRC 8-bit receive in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint8_t tmpreg = *((uint8_t*)&hspi->Instance->DR);
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ hspi->CRCSize--;
+
+ if(hspi->CRCSize == 0)
+ {
+ SPI_CloseRx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Manage the receive 8-bit in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ *hspi->pRxBuffPtr++ = (*(__IO uint8_t *)&hspi->Instance->DR);
+ hspi->RxXferCount--;
+
+ /* Enable CRC Transmission */
+ if((hspi->RxXferCount == 1) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+
+ if(hspi->RxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->RxISR = SPI_RxISR_8BITCRC;
+ return;
+ }
+ SPI_CloseRx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Manage the CRC 16-bit receive in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+ __IO uint16_t tmpreg;
+
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+
+ /* Disable RXNE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ SPI_CloseRx_ISR(hspi);
+}
+
+/**
+ * @brief Manage the 16-bit receive in Interrupt context.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ *((uint16_t *)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+
+ /* Enable CRC Transmission */
+ if((hspi->RxXferCount == 1) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+ {
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+
+ if(hspi->RxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->RxISR = SPI_RxISR_16BITCRC;
+ return;
+ }
+ SPI_CloseRx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Handle the data 8-bit transmit in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr++);
+ hspi->TxXferCount--;
+
+ if(hspi->TxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Enable CRC Transmission */
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+
+ SPI_CloseTx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Handle the data 16-bit transmit in Interrupt mode.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+ /* Transmit data in 16 Bit mode */
+ hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+
+ if(hspi->TxXferCount == 0)
+ {
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ /* Enable CRC Transmission */
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+ SPI_CloseTx_ISR(hspi);
+ }
+}
+
+/**
+ * @brief Handle SPI Communication Timeout.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Flag : SPI flag to check
+ * @param State : flag state to check
+ * @param Timeout : Timeout duration
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, uint32_t State, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while((hspi->Instance->SR & Flag) != State)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) >= Timeout))
+ {
+ /* Disable the SPI and reset the CRC: the CRC value should be cleared
+ on both master and slave sides in order to resynchronize the master
+ and slave for their respective CRC calculation */
+
+ /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+ if((hspi->Init.Mode == SPI_MODE_MASTER)&&((hspi->Init.Direction == SPI_DIRECTION_1LINE)||(hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ hspi->State= HAL_SPI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle SPI FIFO Communication Timeout.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Fifo : Fifo to check
+ * @param State : Fifo state to check
+ * @param Timeout : Timeout duration
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State, uint32_t Timeout)
+{
+ __IO uint8_t tmpreg;
+ uint32_t tickstart = HAL_GetTick();
+
+ while((hspi->Instance->SR & Fifo) != State)
+ {
+ if((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY))
+ {
+ tmpreg = *((__IO uint8_t*)&hspi->Instance->DR);
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) >= Timeout))
+ {
+ /* Disable the SPI and reset the CRC: the CRC value should be cleared
+ on both master and slave sides in order to resynchronize the master
+ and slave for their respective CRC calculation */
+
+ /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+ if((hspi->Init.Mode == SPI_MODE_MASTER)&&((hspi->Init.Direction == SPI_DIRECTION_1LINE)||(hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ }
+
+ /* Reset CRC Calculation */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ SPI_RESET_CRC(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle the check of the RX transaction complete.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param Timeout : Timeout duration
+ * @retval None
+ */
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout)
+{
+ if((hspi->Init.Mode == SPI_MODE_MASTER)&&((hspi->Init.Direction == SPI_DIRECTION_1LINE)||(hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Disable SPI peripheral */
+ __HAL_SPI_DISABLE(hspi);
+ }
+
+ /* Control the BSY flag */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+
+ if((hspi->Init.Mode == SPI_MODE_MASTER)&&((hspi->Init.Direction == SPI_DIRECTION_1LINE)||(hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+ {
+ /* Empty the FRLVL fifo */
+ if(SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle the check of the RXTX or TX transaction complete.
+ * @param hspi: SPI handle
+ * @param Timeout : Timeout duration
+ */
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout)
+{
+ /* Control if the TX fifo is empty */
+ if(SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FTLVL, SPI_FTLVL_EMPTY, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+ /* Control the BSY flag */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle the end of the RXTX transaction.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi)
+{
+ /* Disable ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,SPI_DEFAULT_TIMEOUT)!=HAL_OK)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Check if CRC error occurred */
+ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ else
+ {
+ if(hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+ {
+ if(hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ HAL_SPI_RxCpltCallback(hspi);
+ }
+ else
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ HAL_SPI_TxRxCpltCallback(hspi);
+ }
+ }
+ else
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Handle the end of the RX transaction.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi)
+{
+ /* Disable RXNE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTransaction(hspi,SPI_DEFAULT_TIMEOUT)!=HAL_OK)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_FLAG;
+ }
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Check if CRC error occurred */
+ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_CRC;
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ else
+ {
+ if(hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_RxCpltCallback(hspi);
+ }
+ else
+ {
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ }
+}
+
+/**
+ * @brief Handle the end of the TX transaction.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @retval None
+ */
+static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi)
+{
+ /* Disable TXE and ERR interrupt */
+ __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,SPI_DEFAULT_TIMEOUT)!=HAL_OK)
+ {
+ hspi->ErrorCode|= HAL_SPI_ERROR_FLAG;
+ }
+
+ /* Clear overrun flag in 2 Lines communication mode because received is not read */
+ if(hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ else
+ {
+ HAL_SPI_TxCpltCallback(hspi);
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_spi_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_spi_ex.c
new file mode 100644
index 000000000..18224c859
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_spi_ex.c
@@ -0,0 +1,133 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_spi_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief Extended SPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * SPI peripheral extended functionalities :
+ * + IO operation functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SPIEx SPIEx
+ * @brief SPI Extended HAL module driver
+ * @{
+ */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPIEx_Private_Constants SPIEx Private Constants
+ * @{
+ */
+#define SPI_FIFO_SIZE 4
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup SPIEx_Exported_Functions SPIEx Exported Functions
+ * @{
+ */
+
+/** @defgroup SPIEx_Exported_Functions_Group1 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ==============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of extended functions to manage the SPI
+ data transfers.
+
+ (#) Rx data flush function:
+ (++) HAL_SPIEx_FlushRxFifo()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Flush the RX fifo.
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for the specified SPI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(SPI_HandleTypeDef *hspi)
+{
+ __IO uint32_t tmpreg;
+ uint8_t count = 0;
+ while((hspi->Instance->SR & SPI_FLAG_FRLVL) != SPI_FRLVL_EMPTY)
+ {
+ count++;
+ tmpreg = hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ if(count == SPI_FIFO_SIZE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_tim.c b/stmhal/hal/l4/src/stm32l4xx_hal_tim.c
new file mode 100644
index 000000000..73567062e
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_tim.c
@@ -0,0 +1,5383 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_tim.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief TIM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Timer (TIM) peripheral:
+ * + Time Base Initialization
+ * + Time Base Start
+ * + Time Base Start Interruption
+ * + Time Base Start DMA
+ * + Time Output Compare/PWM Initialization
+ * + Time Output Compare/PWM Channel Configuration
+ * + Time Output Compare/PWM Start
+ * + Time Output Compare/PWM Start Interruption
+ * + Time Output Compare/PWM Start DMA
+ * + Time Input Capture Initialization
+ * + Time Input Capture Channel Configuration
+ * + Time Input Capture Start
+ * + Time Input Capture Start Interruption
+ * + Time Input Capture Start DMA
+ * + Time One Pulse Initialization
+ * + Time One Pulse Channel Configuration
+ * + Time One Pulse Start
+ * + Time Encoder Interface Initialization
+ * + Time Encoder Interface Start
+ * + Time Encoder Interface Start Interruption
+ * + Time Encoder Interface Start DMA
+ * + Commutation Event configuration with Interruption and DMA
+ * + Time OCRef clear configuration
+ * + Time External Clock configuration
+ @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
+
+ ##### 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()
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup TIM TIM
+ * @brief TIM HAL module driver
+ * @{
+ */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+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, uint16_t InputTriggerSource);
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma);
+static void TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+ TIM_SlaveConfigTypeDef * sSlaveConfig);
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup TIM_Exported_Functions TIM Exported Functions
+ * @{
+ */
+
+/** @defgroup TIM_Exported_Functions_Group1 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.
+ * @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));
+
+ if(htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ HAL_TIM_Base_MspInit(htim);
+ }
+
+ /* Set the TIM state */
+ htim->State= HAL_TIM_STATE_BUSY;
+
+ /* Set the Time Base configuration */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Initialize the TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIM_Base_MspDeInit(htim);
+
+ /* 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 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 DeInitialize TIM Base MSP.
+ * @param htim: TIM 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 handle
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Set the TIM state */
+ htim->State= HAL_TIM_STATE_BUSY;
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Change the TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation.
+ * @param htim : TIM handle
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Set the TIM state */
+ htim->State= HAL_TIM_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change 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 handle
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Enable the TIM Update interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation in interrupt mode.
+ * @param htim : TIM 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);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Base generation in DMA mode.
+ * @param htim : TIM 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, uint32_t *pData, uint16_t Length)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if((pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&htim->Instance->ARR, Length);
+
+ /* Enable the TIM Update DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation in DMA mode.
+ * @param htim : TIM 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);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group2 Time Output Compare functions
+ * @brief Time Output Compare functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Time Output Compare functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM Output Compare.
+ (+) De-initialize the TIM Output Compare.
+ (+) Start the Time Output Compare.
+ (+) Stop the Time Output Compare.
+ (+) Start the Time Output Compare and enable interrupt.
+ (+) Stop the Time Output Compare and disable interrupt.
+ (+) Start the Time Output Compare and enable DMA transfer.
+ (+) Stop the Time Output Compare and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Output Compare according to the specified
+ * parameters in the TIM_HandleTypeDef and initialize the associated handle.
+ * @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));
+
+ if(htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_OC_MspInit(htim);
+ }
+
+ /* 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 TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_OC_MspDeInit(htim);
+
+ /* 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 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 DeInitialize TIM Output Compare MSP.
+ * @param htim: TIM 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation.
+ * @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
+ * @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 Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in interrupt mode.
+ * @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
+ * @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_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ 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:
+ break;
+ }
+
+ /* 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @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_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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:
+ break;
+ }
+
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 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, uint32_t *pData, uint16_t Length)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if(((uint32_t)pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length);
+
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length);
+
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length);
+
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length);
+
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @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_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group3 Time PWM functions
+ * @brief Time PWM functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Time PWM functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM OPWM.
+ (+) De-initialize the TIM PWM.
+ (+) Start the Time PWM.
+ (+) Stop the Time PWM.
+ (+) Start the Time PWM and enable interrupt.
+ (+) Stop the Time PWM and disable interrupt.
+ (+) Start the Time PWM and enable DMA transfer.
+ (+) Stop the Time PWM and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM PWM Time Base according to the specified
+ * parameters in the TIM_HandleTypeDef and initialize the associated handle.
+ * @param htim: TIM 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));
+
+ if(htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_PWM_MspInit(htim);
+ }
+
+ /* 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 TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the TIM peripheral
+ * @param htim: TIM 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_PWM_MspDeInit(htim);
+
+ /* 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 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 DeInitialize TIM PWM MSP.
+ * @param htim: TIM 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the PWM signal generation.
+ * @param htim : TIM 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 Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the PWM signal generation in interrupt mode.
+ * @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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ 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:
+ break;
+ }
+
+ /* 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the PWM signal generation in interrupt mode.
+ * @param htim : TIM 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)
+{
+ /* 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:
+ break;
+ }
+
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM PWM signal generation in DMA mode.
+ * @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
+ * @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, uint32_t *pData, uint16_t Length)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if(((uint32_t)pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length);
+
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length);
+
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length);
+
+ /* Enable the TIM Output Capture/Compare 3 request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length);
+
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM PWM signal generation in DMA mode.
+ * @param htim : TIM 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)
+{
+ /* 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);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group4 Time Input Capture functions
+ * @brief Time Input Capture functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Time Input Capture functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM Input Capture.
+ (+) De-initialize the TIM Input Capture.
+ (+) Start the Time Input Capture.
+ (+) Stop the Time Input Capture.
+ (+) Start the Time Input Capture and enable interrupt.
+ (+) Stop the Time Input Capture and disable interrupt.
+ (+) Start the Time Input Capture and enable DMA transfer.
+ (+) Stop the Time 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 initialize the associated handle.
+ * @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));
+
+ if(htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_IC_MspInit(htim);
+ }
+
+ /* 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 TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_IC_MspDeInit(htim);
+
+ /* 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 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 DeInitialize 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement.
+ * @param htim : TIM 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);
+
+ /* 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ 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:
+ break;
+ }
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement in interrupt mode.
+ * @param htim : TIM 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)
+{
+ /* 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:
+ break;
+ }
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Input Capture measurement on 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if((pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length);
+
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData, Length);
+
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->CCR3, (uint32_t)pData, Length);
+
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->CCR4, (uint32_t)pData, Length);
+
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement on 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group5 Time One Pulse functions
+ * @brief Time One Pulse functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Time One Pulse functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM One Pulse.
+ (+) De-initialize the TIM One Pulse.
+ (+) Start the Time One Pulse.
+ (+) Stop the Time One Pulse.
+ (+) Start the Time One Pulse and enable interrupt.
+ (+) Stop the Time One Pulse and disable interrupt.
+ (+) Start the Time One Pulse and enable DMA transfer.
+ (+) Stop the Time 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 initialize the associated handle.
+ * @param htim: TIM OnePulse 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));
+
+ if(htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_OnePulse_MspInit(htim);
+ }
+
+ /* 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 TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIM_OnePulse_MspDeInit(htim);
+
+ /* 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 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 DeInitialize TIM One Pulse MSP.
+ * @param htim: TIM 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.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* 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
+ in all combinations, 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.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : TIM Channels to be 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_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
+ in all combinations, 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 Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation in interrupt mode.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @retval HAL status
+*/
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* 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
+ in all combinations, 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.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @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
+ in all combinations, 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 Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group6 Time Encoder functions
+ * @brief Time Encoder functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Time Encoder functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM Encoder.
+ (+) De-initialize the TIM Encoder.
+ (+) Start the Time Encoder.
+ (+) Stop the Time Encoder.
+ (+) Start the Time Encoder and enable interrupt.
+ (+) Stop the Time Encoder and disable interrupt.
+ (+) Start the Time Encoder and enable DMA transfer.
+ (+) Stop the Time Encoder and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Encoder Interface and initialize the associated handle.
+ * @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 = 0;
+ uint32_t tmpccmr1 = 0;
+ uint32_t tmpccer = 0;
+
+ /* Check the TIM handle allocation */
+ if(htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ 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_IC_POLARITY(sConfig->IC1Polarity));
+ assert_param(IS_TIM_IC_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));
+
+ if(htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_Encoder_MspInit(htim);
+ }
+
+ /* Set the TIM state */
+ htim->State= HAL_TIM_STATE_BUSY;
+
+ /* Reset the SMS bits */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+
+ /* 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 << 8));
+
+ /* 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 << 8);
+ tmpccmr1 |= (sConfig->IC1Filter << 4) | (sConfig->IC2Filter << 12);
+
+ /* 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 << 4);
+
+ /* 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 TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief DeInitialize the TIM Encoder interface
+ * @param htim: TIM Encoder 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIM_Encoder_MspDeInit(htim);
+
+ /* 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 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 DeInitialize TIM Encoder Interface MSP.
+ * @param htim: TIM 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* 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_CC2_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);
+
+ /* 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* 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_CC2_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);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if((((pData1 == 0) || (pData2 == 0) )) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t )pData1, Length);
+
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError;
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2, Length);
+
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ }
+ break;
+
+ case TIM_CHANNEL_ALL:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1, Length);
+
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2, Length);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* 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 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);
+ }
+ break;
+
+ default:
+ 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_DMA_CC_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);
+ }
+ 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);
+ }
+ 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);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+ * @brief 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) != 0x00)
+ {
+ HAL_TIM_IC_CaptureCallback(htim);
+ }
+ /* Output compare event */
+ else
+ {
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+ }
+ 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) != 0x00)
+ {
+ HAL_TIM_IC_CaptureCallback(htim);
+ }
+ /* Output compare event */
+ else
+ {
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+ }
+ 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) != 0x00)
+ {
+ HAL_TIM_IC_CaptureCallback(htim);
+ }
+ /* Output compare event */
+ else
+ {
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+ }
+ 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) != 0x00)
+ {
+ HAL_TIM_IC_CaptureCallback(htim);
+ }
+ /* Output compare event */
+ else
+ {
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+ }
+ 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);
+ HAL_TIM_PeriodElapsedCallback(htim);
+ }
+ }
+ /* 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);
+ HAL_TIMEx_BreakCallback(htim);
+ }
+ }
+ /* 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);
+ HAL_TIM_TriggerCallback(htim);
+ }
+ }
+ /* 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);
+ HAL_TIMEx_CommutationCallback(htim);
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group8 Peripheral Control functions
+ * @brief 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 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
+ */
+__weak HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel)
+{
+ /* 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));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ {
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+ /* Configure the TIM Channel 4 in Output Compare */
+ TIM_OC4_SetConfig(htim->Instance, sConfig);
+ }
+ break;
+
+ default:
+ break;
+ }
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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 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_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef* sConfig, uint32_t Channel)
+{
+ /* 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));
+
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ 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 << 8);
+ }
+ 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
+ {
+ /* 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 << 8);
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM PWM channels according to the specified
+ * parameters in the TIM_OC_InitTypeDef.
+ * @param htim: TIM handle
+ * @param sConfig: TIM PWM configuration structure
+ * @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
+ */
+__weak HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel)
+{
+ __HAL_LOCK(htim);
+
+ /* 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));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ 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:
+ {
+ 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 << 8;
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ 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:
+ {
+ 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 << 8;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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 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
+ * @param InputChannel : 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
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef* sConfig, uint32_t OutputChannel, uint32_t InputChannel)
+{
+ TIM_OC_InitTypeDef temp1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_OPM_CHANNELS(OutputChannel));
+ assert_param(IS_TIM_OPM_CHANNELS(InputChannel));
+
+ if(OutputChannel != InputChannel)
+ {
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Extract the Ouput 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:
+ break;
+ }
+ 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:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+ 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 when the DMA will starts the Data write
+ * This parameters can be on 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_DCR
+ * @param BurstRequestSrc: TIM DMA Request sources
+ * This parameters can be on 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.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc,
+ uint32_t* BurstBuffer, uint32_t BurstLength)
+{
+ /* 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));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if((BurstBuffer == 0 ) && (BurstLength > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ switch(BurstRequestSrc)
+ {
+ case TIM_DMA_UPDATE:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC3:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_COM:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_TRIGGER:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ default:
+ break;
+ }
+ /* configure the DMA Burst Mode */
+ htim->Instance->DCR = BurstBaseAddress | BurstLength;
+
+ /* Enable the TIM DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* 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:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_UPDATE]);
+ }
+ break;
+ case TIM_DMA_CC1:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC1]);
+ }
+ break;
+ case TIM_DMA_CC2:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC2]);
+ }
+ break;
+ case TIM_DMA_CC3:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC3]);
+ }
+ break;
+ case TIM_DMA_CC4:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC4]);
+ }
+ break;
+ case TIM_DMA_COM:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+ }
+ break;
+ case TIM_DMA_TRIGGER:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_TRIGGER]);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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 when the DMA will starts the Data read
+ * This parameters can be on 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_DCR
+ * @param BurstRequestSrc: TIM DMA Request sources
+ * This parameters can be on 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.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc,
+ uint32_t *BurstBuffer, uint32_t BurstLength)
+{
+ /* 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));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if((BurstBuffer == 0 ) && (BurstLength > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ switch(BurstRequestSrc)
+ {
+ case TIM_DMA_UPDATE:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC3:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_CC4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_COM:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ case TIM_DMA_TRIGGER:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* configure the DMA Burst Mode */
+ htim->Instance->DCR = BurstBaseAddress | BurstLength;
+
+ /* Enable the TIM DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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)
+{
+ /* 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:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_UPDATE]);
+ }
+ break;
+ case TIM_DMA_CC1:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC1]);
+ }
+ break;
+ case TIM_DMA_CC2:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC2]);
+ }
+ break;
+ case TIM_DMA_CC3:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC3]);
+ }
+ break;
+ case TIM_DMA_CC4:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC4]);
+ }
+ break;
+ case TIM_DMA_COM:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+ }
+ break;
+ case TIM_DMA_TRIGGER:
+ {
+ HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_TRIGGER]);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @retval None
+ */
+
+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
+ * @retval HAL status
+ */
+__weak HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, TIM_ClearInputConfigTypeDef * sClearInputConfig, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_CHANNELS(Channel));
+ assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ if(sClearInputConfig->ClearInputSource == 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));
+
+ TIM_ETR_SetConfig(htim->Instance,
+ sClearInputConfig->ClearInputPrescaler,
+ sClearInputConfig->ClearInputPolarity,
+ sClearInputConfig->ClearInputFilter);
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC1CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_2:
+ {
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 2 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC2CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 2 */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_3:
+ {
+ assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 3 */
+ htim->Instance->CCMR2 |= TIM_CCMR2_OC3CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 3 */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_4:
+ {
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 4 */
+ htim->Instance->CCMR2 |= TIM_CCMR2_OC4CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 4 */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4CE;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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, TIM_ClockConfigTypeDef * sClockSourceConfig)
+{
+ uint32_t tmpsmcr = 0;
+
+ /* 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));
+ /* Disable slave mode to clock the prescaler directly with the internal clock */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+ }
+ 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);
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = htim->Instance->SMCR;
+ /* Reset the SMS and TS Bits */
+ tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
+ /* Select the External clock mode1 and the ETRF trigger */
+ 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:
+ {
+ /* 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, TIM_CLOCKSOURCE_ITR0);
+ }
+ break;
+
+ case TIM_CLOCKSOURCE_ITR1:
+ {
+ /* 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, TIM_CLOCKSOURCE_ITR1);
+ }
+ break;
+
+ case TIM_CLOCKSOURCE_ITR2:
+ {
+ /* 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, TIM_CLOCKSOURCE_ITR2);
+ }
+ break;
+
+ 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, TIM_CLOCKSOURCE_ITR3);
+ }
+ break;
+
+ default:
+ break;
+ }
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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 = 0;
+
+ /* 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 ) and the Slave
+ * mode (Disable, Reset, Gated, Trigger, External clock mode 1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization(TIM_HandleTypeDef *htim, 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;
+
+ TIM_SlaveTimer_SetConfig(htim, sSlaveConfig);
+
+ /* 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 ) and the Slave
+ * mode (Disable, Reset, Gated, Trigger, External clock mode 1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization_IT(TIM_HandleTypeDef *htim,
+ 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;
+
+ TIM_SlaveTimer_SetConfig(htim, sSlaveConfig);
+
+ /* 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(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpreg = 0;
+
+ __HAL_LOCK(htim);
+
+ 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;
+ }
+
+ __HAL_UNLOCK(htim);
+ return tmpreg;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions
+ * @brief TIM Callbacks functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM Callbacks functions #####
+ ==============================================================================
+ [..]
+ This section provides TIM callback functions:
+ (+) Timer Period elapsed callback
+ (+) Timer Output Compare callback
+ (+) Timer Input capture callback
+ (+) Timer Trigger callback
+ (+) Timer 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 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 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 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 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
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group10 Peripheral State functions
+ * @brief 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(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM OC handle state.
+ * @param htim: TIM Ouput Compare handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(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(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(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(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Encoder Mode handle state.
+ * @param htim: TIM Encoder handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @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;
+
+ htim->State= HAL_TIM_STATE_READY;
+
+ HAL_TIM_ErrorCallback(htim);
+}
+
+/**
+ * @brief TIM DMA Delay Pulse complete callback.
+ * @param hdma : pointer to DMA handle.
+ * @retval None
+ */
+void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ htim->State= HAL_TIM_STATE_READY;
+
+ 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;
+ }
+
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+
+ 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;
+
+ htim->State= HAL_TIM_STATE_READY;
+
+ 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;
+ }
+
+ HAL_TIM_IC_CaptureCallback(htim);
+
+ 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;
+
+ htim->State= HAL_TIM_STATE_READY;
+
+ HAL_TIM_PeriodElapsedCallback(htim);
+}
+
+/**
+ * @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;
+
+ htim->State= HAL_TIM_STATE_READY;
+
+ HAL_TIM_TriggerCallback(htim);
+}
+
+/**
+ * @brief Time Base configuration
+ * @param TIMx: TIM peripheral
+ * @param Structure: TIM Base configuration structure
+ * @retval None
+ */
+void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure)
+{
+ uint32_t tmpcr1 = 0;
+ 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;
+ }
+
+ TIMx->CR1 = tmpcr1;
+
+ /* Set the Autoreload value */
+ TIMx->ARR = (uint32_t)Structure->Period ;
+
+ /* Set the Prescaler value */
+ TIMx->PSC = (uint32_t)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 TIM1 and TIM8) value immediately */
+ TIMx->EGR = TIM_EGR_UG;
+}
+
+/**
+ * @brief Time Ouput Compare 1 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The ouput configuration structure
+ * @retval None
+ */
+void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx = 0;
+ uint32_t tmpccer = 0;
+ uint32_t tmpcr2 = 0;
+
+ /* 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 Time Ouput Compare 2 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The ouput configuration structure
+ * @retval None
+ */
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx = 0;
+ uint32_t tmpccer = 0;
+ uint32_t tmpcr2 = 0;
+
+ /* 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 << 8);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC2P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 4);
+
+ 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 << 4);
+ /* 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 << 2);
+ /* Set the Output N Idle state */
+ tmpcr2 |= (OC_Config->OCNIdleState << 2);
+ }
+
+ /* 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 Time Ouput Compare 3 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The ouput configuration structure
+ * @retval None
+ */
+void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx = 0;
+ uint32_t tmpccer = 0;
+ uint32_t tmpcr2 = 0;
+
+ /* 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 << 8);
+
+ 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 << 8);
+ /* 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 << 4);
+ /* Set the Output N Idle state */
+ tmpcr2 |= (OC_Config->OCNIdleState << 4);
+ }
+
+ /* 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 Time Ouput Compare 4 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The ouput configuration structure
+ * @retval None
+ */
+void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx = 0;
+ uint32_t tmpccer = 0;
+ uint32_t tmpcr2 = 0;
+
+ /* 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 << 8);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC4P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 12);
+
+ if(IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ 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 << 6);
+ }
+
+ /* 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;
+}
+
+static void TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+ TIM_SlaveConfigTypeDef * sSlaveConfig)
+{
+ uint32_t tmpsmcr = 0;
+ uint32_t tmpccmr1 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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));
+
+ /* 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) << 4);
+
+ /* 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:
+ {
+ /* Check the parameter */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ }
+ break;
+
+ case TIM_TS_ITR1:
+ {
+ /* Check the parameter */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ }
+ break;
+
+ case TIM_TS_ITR2:
+ {
+ /* Check the parameter */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ }
+ break;
+
+ case TIM_TS_ITR3:
+ {
+ /* Check the parameter */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @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 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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 << 4) & 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 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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 << 4);
+
+ /* 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 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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 << 8);
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC2F;
+ tmpccmr1 |= ((TIM_ICFilter << 12) & TIM_CCMR1_IC2F);
+
+ /* Select the Polarity and set the CC2E Bit */
+ tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= ((TIM_ICPolarity << 4) & (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 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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 << 12);
+
+ /* Select the Polarity and set the CC2E Bit */
+ tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= (TIM_ICPolarity << 4);
+
+ /* 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 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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 << 4) & TIM_CCMR2_IC3F);
+
+ /* Select the Polarity and set the CC3E Bit */
+ tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+ tmpccer |= ((TIM_ICPolarity << 8) & (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 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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 << 8);
+
+ /* Set the filter */
+ tmpccmr2 &= ~TIM_CCMR2_IC4F;
+ tmpccmr2 |= ((TIM_ICFilter << 12) & TIM_CCMR2_IC4F);
+
+ /* Select the Polarity and set the CC4E Bit */
+ tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP);
+ tmpccer |= ((TIM_ICPolarity << 12) & (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, uint16_t InputTriggerSource)
+{
+ uint32_t tmpsmcr = 0;
+
+ /* 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 = 0;
+
+ 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 << 8)));
+
+ /* 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
+ * @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 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+ assert_param(IS_TIM_CHANNELS(Channel));
+
+ tmp = TIM_CCER_CC1E << Channel;
+
+ /* Reset the CCxE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelState << Channel);
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_tim_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_tim_ex.c
new file mode 100644
index 000000000..4c63f2cfb
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_tim_ex.c
@@ -0,0 +1,2711 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_tim_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @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
+ @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_ConfigCommutationEvent(): 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_OC_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+*/
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup TIMEx TIMEx
+ * @brief TIM Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define BDTR_BKF_SHIFT (16)
+#define BDTR_BK2F_SHIFT (20)
+#define TIMx_ETRSEL_MASK ((uint32_t)0x0001C000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx,
+ TIM_OC_InitTypeDef *OC_Config);
+
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx,
+ TIM_OC_InitTypeDef *OC_Config);
+
+static void TIM_CCxNChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelNState);
+
+/* Private functions ---------------------------------------------------------*/
+/**
+ * @brief Timer Ouput Compare 5 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx,
+ TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx = 0;
+ uint32_t tmpccer = 0;
+ uint32_t tmpcr2 = 0;
+
+ /* 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 << 16);
+
+ 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 << 8);
+ }
+ /* 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 Ouput Compare 6 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The ouput configuration structure
+ * @retval None
+ */
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx,
+ TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx = 0;
+ uint32_t tmpccer = 0;
+ uint32_t tmpcr2 = 0;
+
+ /* 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 << 8);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= (uint32_t)~TIM_CCER_CC6P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 20);
+
+ 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 << 10);
+ }
+
+ /* 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;
+}
+
+/* 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.
+ * @param htim: TIM Encoder Interface handle
+ * @param sConfig: TIM Hall Sensor configuration structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef* sConfig)
+{
+ TIM_OC_InitTypeDef OC_Config;
+
+ /* Check the TIM handle allocation */
+ if(htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ assert_param(IS_TIM_XOR_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_IC_POLARITY(sConfig->IC1Polarity));
+ 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;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIMEx_HallSensor_MspInit(htim);
+ }
+
+ /* 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 TIM state*/
+ htim->State= HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the TIM Hall Sensor interface
+ * @param htim: TIM Hall Sensor 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);
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIMEx_HallSensor_MspDeInit(htim);
+
+ /* 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 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 DeInitialize TIM Hall Sensor MSP.
+ * @param htim: TIM 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 handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+
+ /* Enable the Input Capture channels 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Hall sensor Interface.
+ * @param htim : TIM Hall Sensor handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_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);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Hall Sensor Interface in interrupt mode.
+ * @param htim : TIM Hall Sensor handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+
+ /* Enable the capture compare Interrupts 1 event */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+ /* Enable the Input Capture channels 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 */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Hall Sensor Interface in interrupt mode.
+ * @param htim : TIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channels 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);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Hall Sensor Interface in DMA mode.
+ * @param htim : TIM Hall Sensor 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)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if(((uint32_t)pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ /* Enable the Input Capture channels 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 Callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel for Capture 1*/
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length);
+
+ /* Enable the capture compare 1 Interrupt */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Hall Sensor Interface in DMA mode.
+ * @param htim : TIM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channels 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);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* 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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral */
+ __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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 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 Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* 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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ 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;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* 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 Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpccer = 0;
+
+ /* 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;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Output Compare interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* 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)) == RESET)
+ {
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+ }
+
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @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_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if(((uint32_t)pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length);
+
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length);
+
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+{
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length);
+
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length);
+
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Output Compare DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Output Compare DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Output Compare interrupt */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Disable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral */
+ __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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 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 Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* 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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ 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:
+ break;
+ }
+
+ /* 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 Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT (TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpccer = 0;
+
+ /* 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;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* 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)) == RESET)
+ {
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+ }
+
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @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_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ if((htim->State == HAL_TIM_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if((htim->State == HAL_TIM_STATE_READY))
+ {
+ if(((uint32_t)pData == 0 ) && (Length > 0))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length);
+
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length);
+
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length);
+
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA Period elapsed callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA channel */
+ HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length);
+
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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);
+ }
+ break;
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ }
+ break;
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ }
+ break;
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Disable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @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.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Enable the complementary One Pulse output */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Ouput */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation on the complementary
+ * output.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Disable the complementary One Pulse output */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation in interrupt mode on the
+ * complementary channel.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* 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 */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Ouput */
+ __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.
+ * @param htim : TIM One Pulse handle
+ * @param OutputChannel : 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
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* 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 */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Ouput */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* 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_ConfigCommutationEvent(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;
+
+ __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_ConfigCommutationEvent_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;
+
+ /* Enable the Commutation Interrupt Request */
+ __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_ConfigCommutationEvent_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;
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError;
+
+ /* Enable the Commutation DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM);
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_ALL: all output channels supported by the timer instance selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim,
+ TIM_OC_InitTypeDef* sConfig,
+ uint32_t Channel)
+{
+ /* 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));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ 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:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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
+ * @arg TIM_CHANNEL_ALL: all PWM channels supported by the timer instance selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
+ TIM_OC_InitTypeDef* sConfig,
+ uint32_t Channel)
+{
+ /* 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));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ 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 << 8;
+ }
+ 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 << 8;
+ }
+ 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 5 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 << 8;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ 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 None
+ */
+HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim,
+ TIM_ClearInputConfigTypeDef *sClearInputConfig,
+ uint32_t Channel)
+{
+ uint32_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_OCXREF_CLEAR_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ switch (sClearInputConfig->ClearInputSource)
+ {
+ case TIM_CLEARINPUTSOURCE_NONE:
+ {
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = htim->Instance->SMCR;
+
+ /* Clear the OCREF clear selection bit */
+ tmpsmcr &= ~TIM_SMCR_OCCS;
+
+ /* Clear the ETR Bits */
+ tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+
+ /* Set TIMx_SMCR */
+ htim->Instance->SMCR = tmpsmcr;
+ }
+ break;
+
+ case TIM_CLEARINPUTSOURCE_OCREFCLR:
+ {
+ /* Clear the OCREF clear selection bit */
+ htim->Instance->SMCR &= ~TIM_SMCR_OCCS;
+ }
+ 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));
+
+ TIM_ETR_SetConfig(htim->Instance,
+ sClearInputConfig->ClearInputPrescaler,
+ sClearInputConfig->ClearInputPolarity,
+ sClearInputConfig->ClearInputFilter);
+
+ /* Set the OCREF clear selection bit */
+ htim->Instance->SMCR |= TIM_SMCR_OCCS;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC1CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_2:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 2 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC2CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 2 */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_3:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 3 */
+ htim->Instance->CCMR2 |= TIM_CCMR2_OC3CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 3 */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_4:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 4 */
+ htim->Instance->CCMR2 |= TIM_CCMR2_OC4CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 4 */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_5:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR3 |= TIM_CCMR3_OC5CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5CE;
+ }
+ }
+ break;
+ case TIM_CHANNEL_6:
+ {
+ if(sClearInputConfig->ClearInputState != RESET)
+ {
+ /* Enable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR3 |= TIM_CCMR3_OC6CE;
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 1 */
+ htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6CE;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ __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,
+ TIM_MasterConfigTypeDef * sMasterConfig)
+{
+ uint32_t tmpcr2;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_SYNCHRO_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);
+
+ /* 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;
+
+ /* Reset the MSM Bit */
+ tmpsmcr &= ~TIM_SMCR_MSM;
+ /* Set master mode */
+ tmpsmcr |= sMasterConfig->MasterSlaveMode;
+
+ /* Update TIMx CR2 */
+ htim->Instance->CR2 = tmpcr2;
+
+ /* Update TIMx SMCR */
+ htim->Instance->SMCR = tmpsmcr;
+
+ __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.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
+ TIM_BreakDeadTimeConfigTypeDef * sBreakDeadTimeConfig)
+{
+ uint32_t tmpbdtr = 0;
+
+ /* 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 */
+ if (IS_TIM_BKIN2_INSTANCE(htim->Instance))
+ {
+ assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State));
+ assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity));
+ assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter));
+
+ /* Clear the BDTR bits */
+ tmpbdtr &= ~(TIM_BDTR_DTG | TIM_BDTR_LOCK | TIM_BDTR_OSSI |
+ TIM_BDTR_OSSR | TIM_BDTR_BKE | TIM_BDTR_BKP |
+ TIM_BDTR_AOE | TIM_BDTR_MOE | TIM_BDTR_BKF |
+ TIM_BDTR_BK2F | TIM_BDTR_BK2E | TIM_BDTR_BK2P);
+
+ /* Set the BDTR bits */
+ tmpbdtr |= sBreakDeadTimeConfig->DeadTime;
+ tmpbdtr |= sBreakDeadTimeConfig->LockLevel;
+ tmpbdtr |= sBreakDeadTimeConfig->OffStateIDLEMode;
+ tmpbdtr |= sBreakDeadTimeConfig->OffStateRunMode;
+ tmpbdtr |= sBreakDeadTimeConfig->BreakState;
+ tmpbdtr |= sBreakDeadTimeConfig->BreakPolarity;
+ tmpbdtr |= sBreakDeadTimeConfig->AutomaticOutput;
+ tmpbdtr |= (sBreakDeadTimeConfig->BreakFilter << BDTR_BKF_SHIFT);
+ tmpbdtr |= (sBreakDeadTimeConfig->Break2Filter << BDTR_BK2F_SHIFT);
+ tmpbdtr |= sBreakDeadTimeConfig->Break2State;
+ tmpbdtr |= sBreakDeadTimeConfig->Break2Polarity;
+ }
+ else
+ {
+ /* Clear the BDTR bits */
+ tmpbdtr &= ~(TIM_BDTR_DTG | TIM_BDTR_LOCK | TIM_BDTR_OSSI |
+ TIM_BDTR_OSSR | TIM_BDTR_BKE | TIM_BDTR_BKP |
+ TIM_BDTR_AOE | TIM_BDTR_MOE | TIM_BDTR_BKF);
+
+ /* Set the BDTR bits */
+ tmpbdtr |= sBreakDeadTimeConfig->DeadTime;
+ tmpbdtr |= sBreakDeadTimeConfig->LockLevel;
+ tmpbdtr |= sBreakDeadTimeConfig->OffStateIDLEMode;
+ tmpbdtr |= sBreakDeadTimeConfig->OffStateRunMode;
+ tmpbdtr |= sBreakDeadTimeConfig->BreakState;
+ tmpbdtr |= sBreakDeadTimeConfig->BreakPolarity;
+ tmpbdtr |= sBreakDeadTimeConfig->AutomaticOutput;
+ tmpbdtr |= (sBreakDeadTimeConfig->BreakFilter << BDTR_BKF_SHIFT);
+ }
+
+ /* 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,
+ TIMEx_BreakInputConfigTypeDef *sBreakInputConfig)
+
+{
+ uint32_t tmporx = 0;
+ uint32_t bkin_enable_mask = 0;
+ uint32_t bkin_polarity_mask = 0;
+ uint32_t bkin_enable_bitpos = 0;
+ uint32_t bkin_polarity_bitpos = 0;
+
+ /* 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));
+
+ if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM)
+ {
+ 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_OR2_BKINE;
+ bkin_enable_bitpos = 0;
+ bkin_polarity_mask = TIM1_OR2_BKINP;
+ bkin_polarity_bitpos = 9;
+ }
+ break;
+ case TIM_BREAKINPUTSOURCE_COMP1:
+ {
+ bkin_enable_mask = TIM1_OR2_BKCMP1E;
+ bkin_enable_bitpos = 1;
+ bkin_polarity_mask = TIM1_OR2_BKCMP1P;
+ bkin_polarity_bitpos = 10;
+ }
+ break;
+ case TIM_BREAKINPUTSOURCE_COMP2:
+ {
+ bkin_enable_mask = TIM1_OR2_BKCMP2E;
+ bkin_enable_bitpos = 2;
+ bkin_polarity_mask = TIM1_OR2_BKCMP2P;
+ bkin_polarity_bitpos = 11;
+ }
+ break;
+ case TIM_BREAKINPUTSOURCE_DFSDM:
+ {
+ bkin_enable_mask = TIM1_OR2_BKDFBK0E;
+ bkin_enable_bitpos = 8;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch(BreakInput)
+ {
+ case TIM_BREAKINPUT_BRK:
+ {
+ /* Get the TIMx_OR2 register value */
+ tmporx = htim->Instance->OR2;
+
+ /* Enable the break input */
+ tmporx &= ~bkin_enable_mask;
+ tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
+
+ /* Set the break input polarity */
+ if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM)
+ {
+ tmporx &= ~bkin_polarity_mask;
+ tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
+ }
+
+ /* Set TIMx_OR2 */
+ htim->Instance->OR2 = tmporx;
+ }
+ break;
+ case TIM_BREAKINPUT_BRK2:
+ {
+ /* Get the TIMx_OR3 register value */
+ tmporx = htim->Instance->OR3;
+
+ /* Enable the break input */
+ tmporx &= ~bkin_enable_mask;
+ tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
+
+ /* Set the break input polarity */
+ if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM)
+ {
+ tmporx &= ~bkin_polarity_mask;
+ tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
+ }
+
+ /* Set TIMx_OR3 */
+ htim->Instance->OR3 = tmporx;
+ }
+ break;
+ default:
+ break;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @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 4 fields (field1 | field2 | field3 | field4):
+ *
+ * field1 can have the following values:
+ * @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog)
+ * @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
+ *
+ * field2 can have the following values:
+ * @arg TIM_TIM1_ETR_ADC3_NONE: TIM1_ETR is not connected to any ADC3 AWD (analog watchdog)
+ * @arg TIM_TIM1_ETR_ADC3_AWD1: TIM1_ETR is connected to ADC3 AWD1
+ * @arg TIM_TIM1_ETR_ADC3_AWD2: TIM1_ETR is connected to ADC3 AWD2
+ * @arg TIM_TIM1_ETR_ADC3_AWD3: TIM1_ETR is connected to ADC3 AWD3
+ *
+ * field3 can have the following values:
+ * @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO
+ * @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output
+ *
+ * field4 can have the following values:
+ * @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output
+ * @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output
+ * @note When field4 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 and field2 values are not significant
+ *
+ * For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3):
+ *
+ * field1 can have the following values:
+ * @arg TIM_TIM2_ITR1_TIM8_TRGO: TIM2_ITR1 is connected to TIM8_TRGO
+ * @arg TIM_TIM2_ITR1_OTG_FS_SOF: TIM2_ITR1 is connected to OTG_FS SOF
+ *
+ * field2 can have the following values:
+ * @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO
+ * @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 GPIO
+ * @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 TIM3, the parameter is a combination 2 fields(field1 | field2):
+ *
+ * field1 can have the following values:
+ * @arg TIM_TIM3_TI1_GPIO: TIM3 TI1 is connected to GPIO
+ * @arg TIM_TIM3_TI1_COMP1: TIM3 TI1 is connected to COMP1 output
+ * @arg TIM_TIM3_TI1_COMP2: TIM3 TI1 is connected to COMP2 output
+ * @arg TIM_TIM3_TI1_COMP1_COMP2: TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output
+ *
+ * field2 can have the following values:
+ * @arg TIM_TIM3_ETR_GPIO: TIM3_ETR is connected to GPIO
+ * @arg TIM_TIM3_ETR_COMP1: TIM3_ETR is connected to COMP1 output
+ *
+ * For TIM8, the parameter is a combination of 3 fields (field1 | field2 | field3):
+ *
+ * field1 can have the following values:
+ * @arg TIM_TIM8_ETR_ADC2_NONE: TIM8_ETR is not connected to any ADC2 AWD (analog watchdog)
+ * @arg TIM_TIM8_ETR_ADC2_AWD1: TIM8_ETR is connected to ADC2 AWD1
+ * @arg TIM_TIM8_ETR_ADC2_AWD2: TIM8_ETR is connected to ADC2 AWD2
+ * @arg TIM_TIM8_ETR_ADC2_AWD3: TIM8_ETR is connected to ADC2 AWD3
+ *
+ * field2 can have the following values:
+ * @arg TIM_TIM8_ETR_ADC3_NONE: TIM8_ETR is not connected to any ADC3 AWD (analog watchdog)
+ * @arg TIM_TIM8_ETR_ADC3_AWD1: TIM8_ETR is connected to ADC3 AWD1
+ * @arg TIM_TIM8_ETR_ADC3_AWD2: TIM8_ETR is connected to ADC3 AWD2
+ * @arg TIM_TIM8_ETR_ADC3_AWD3: TIM8_ETR is connected to ADC3 AWD3
+ *
+ * field3 can have the following values:
+ * @arg TIM_TIM8_TI1_GPIO: TIM8 TI1 is connected to GPIO
+ * @arg TIM_TIM8_TI1_COMP2: TIM8 TI1 is connected to COMP2 output
+ *
+ * field4 can have the following values:
+ * @arg TIM_TIM8_ETR_COMP1: TIM8_ETR is connected to COMP1 output
+ * @arg TIM_TIM8_ETR_COMP2: TIM8_ETR is connected to COMP2 output
+ * @note When field4 is set to TIM_TIM8_ETR_COMP1 or TIM_TIM8_ETR_COMP2 field1 and field2 values are not significant
+ *
+ * For TIM15, the parameter is a combination of 3 fields (field1 | field2):
+ *
+ * field1 can have the following values:
+ * @arg TIM_TIM15_TI1_GPIO: TIM15 TI1 is connected to GPIO
+ * @arg TIM_TIM15_TI1_LSE: TIM15 TI1 is connected to LSE
+ *
+ * field2 can have the following values:
+ * @arg TIM_TIM15_ENCODERMODE_NONE: No redirection
+ * @arg TIM_TIM15_ENCODERMODE_TIM2: TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
+ * @arg TIM_TIM15_ENCODERMODE_TIM3: TIM3 IC1 and TIM3 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
+ * @arg TIM_TIM15_ENCODERMODE_TIM4: TIM4 IC1 and TIM4 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
+ *
+ * For TIM16, the parameter can have the following values:
+ * @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO
+ * @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 GPIO
+ * @arg TIM_TIM17_TI1_MSI: TIM17 TI1 is connected to MSI (contraints: MSI clock < 1/4 TIM APB clock)
+ * @arg TIM_TIM17_TI1_HSE_32: TIM17 TI1 is connected to HSE div 32
+ * @arg TIM_TIM17_TI1_MCO: TIM17 TI1 is connected to MCO
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
+{
+ uint32_t tmpor1 = 0;
+ uint32_t tmpor2 = 0;
+
+ __HAL_LOCK(htim);
+
+ /* Check parameters */
+ assert_param(IS_TIM_REMAP_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_REMAP(Remap));
+
+ /* Set ETR_SEL bit field (if required) */
+ if (IS_TIM_ETRSEL_INSTANCE(htim->Instance))
+ {
+ tmpor2 = htim->Instance->OR2;
+ tmpor2 &= ~TIMx_ETRSEL_MASK;
+ tmpor2 |= (Remap & TIMx_ETRSEL_MASK);
+
+ /* Set TIMx_OR2 */
+ htim->Instance->OR2 = tmpor2;
+ }
+
+ /* Set other remapping capabilities */
+ tmpor1 = Remap;
+ tmpor1 &= ~TIMx_ETRSEL_MASK;
+
+ /* Set TIMx_OR1 */
+ htim->Instance->OR1 = Remap;
+
+ /* Set TIMx_OR1 */
+ htim->Instance->OR1 = tmpor1;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __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;
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @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_CommutationCallback(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_CommutationCallback 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
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @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(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @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;
+
+ htim->State= HAL_TIM_STATE_READY;
+
+ HAL_TIMEx_CommutationCallback(htim);
+}
+
+/**
+ * @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 = 0;
+
+ tmp = TIM_CCER_CC1NE << Channel;
+
+ /* Reset the CCxNE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxNE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelNState << Channel);
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_uart.c b/stmhal/hal/l4/src/stm32l4xx_hal_uart.c
new file mode 100644
index 000000000..e35c4db8e
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_uart.c
@@ -0,0 +1,2117 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_uart.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief UART HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ *
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The UART HAL driver can be used as follows:
+
+ (#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart).
+ (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:
+ (++) Enable the USARTx interface clock.
+ (++) UART pins configuration:
+ (+++) Enable the clock for the UART GPIOs.
+ (+++) Configure these UART pins as alternate function pull-up.
+ (++) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()
+ and HAL_UART_Receive_IT() APIs):
+ (+++) Configure the USARTx interrupt priority.
+ (+++) Enable the NVIC USART IRQ handle.
+ (++) UART interrupts handling:
+ -@@- The specific UART interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) are managed using the macros
+ __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit and receive processes.
+ (++) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA()
+ and HAL_UART_Receive_DMA() APIs):
+ (+++) Declare a DMA handle structure for the Tx/Rx channel.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx channel.
+ (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
+
+ (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
+ flow control and Mode (Receiver/Transmitter) in the huart handle Init structure.
+
+ (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...)
+ in the huart handle AdvancedInit structure.
+
+ (#) For the UART asynchronous mode, initialize the UART registers by calling
+ the HAL_UART_Init() API.
+
+ (#) For the UART Half duplex mode, initialize the UART registers by calling
+ the HAL_HalfDuplex_Init() API.
+
+ (#) For the UART LIN (Local Interconnection Network) mode, initialize the UART registers
+ by calling the HAL_LIN_Init() API.
+
+ (#) For the UART Multiprocessor mode, initialize the UART registers
+ by calling the HAL_MultiProcessor_Init() API.
+
+ (#) For the UART RS485 Driver Enabled mode, initialize the UART registers
+ by calling the HAL_RS485Ex_Init() API.
+
+ [..]
+ (@) These API's (HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), HAL_MultiProcessor_Init(),
+ also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by
+ calling the customized HAL_UART_MspInit() API.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup UART UART
+ * @brief HAL UART module driver
+ * @{
+ */
+
+#ifdef HAL_UART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup UART_Private_Constants UART Private Constants
+ * @{
+ */
+#define UART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */
+
+#define UART_LPUART_BRR_MIN ((uint32_t)0x00000300) /* LPUART BRR minimum authorized value */
+#define UART_LPUART_BRR_MAX ((uint32_t)0x000FFFFF) /* LPUART BRR maximum authorized value */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup UART_Private_Functions
+ * @{
+ */
+static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void UART_DMAError(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart);
+static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart);
+static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup UART_Exported_Functions UART Exported Functions
+ * @{
+ */
+
+/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
+ in asynchronous mode.
+ (+) For the asynchronous mode the parameters below can be configured:
+ (++) Baud Rate
+ (++) Word Length
+ (++) Stop Bit
+ (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ (++) Hardware flow control
+ (++) Receiver/transmitter modes
+ (++) Over Sampling Method
+ (++) One-Bit Sampling Method
+ (+) For the asynchronous mode, the following advanced features can be configured as well:
+ (++) TX and/or RX pin level inversion
+ (++) data logical level inversion
+ (++) RX and TX pins swap
+ (++) RX overrun detection disabling
+ (++) DMA disabling on RX error
+ (++) MSB first on communication line
+ (++) auto Baud rate detection
+ [..]
+ The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()API
+ follow respectively the UART asynchronous, UART Half duplex, UART LIN mode
+ and UART multiprocessor mode configuration procedures (details for the procedures
+ are available in reference manual).
+
+@endverbatim
+
+ Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ 8-bit or 9-bit), the possible UART formats are listed in the
+ following table.
+
+ Table 1. UART frame format.
+ +-----------------------------------------------------------------------+
+ | M1 bit | M0 bit | PCE bit | UART frame |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ +-----------------------------------------------------------------------+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the UART mode according to the specified
+ * parameters in the UART_InitTypeDef and initialize the associated handle.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)
+ {
+ /* Check the parameters */
+ assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance)));
+ }
+
+ if(huart->State == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+ }
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In asynchronous mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
+ huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN);
+ huart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->State to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Initialize the half-duplex mode according to the specified
+ * parameters in the UART_InitTypeDef and creates the associated handle.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check UART instance */
+ assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance));
+
+ if(huart->State == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+ }
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In half-duplex mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN and IREN bits in the USART_CR3 register.*/
+ huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN);
+ huart->Instance->CR3 &= ~(USART_CR3_IREN | USART_CR3_SCEN);
+
+ /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
+ huart->Instance->CR3 |= USART_CR3_HDSEL;
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->State to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+/**
+ * @brief Initialize the LIN mode according to the specified
+ * parameters in the UART_InitTypeDef and creates the associated handle .
+ * @param huart: UART handle.
+ * @param BreakDetectLength: specifies the LIN break detection length.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_LINBREAKDETECTLENGTH_10B 10-bit break detection
+ * @arg @ref UART_LINBREAKDETECTLENGTH_11B 11-bit break detection
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength)
+{
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the LIN UART instance */
+ assert_param(IS_UART_LIN_INSTANCE(huart->Instance));
+ /* Check the Break detection length parameter */
+ assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength));
+
+ /* LIN mode limited to 16-bit oversampling only */
+ if(huart->Init.OverSampling == UART_OVERSAMPLING_8)
+ {
+ return HAL_ERROR;
+ }
+ /* LIN mode limited to 8-bit data length */
+ if(huart->Init.WordLength != UART_WORDLENGTH_8B)
+ {
+ return HAL_ERROR;
+ }
+
+ if(huart->State == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+ }
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In LIN mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN and IREN bits in the USART_CR3 register.*/
+ huart->Instance->CR2 &= ~(USART_CR2_CLKEN);
+ huart->Instance->CR3 &= ~(USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN);
+
+ /* Enable the LIN mode by setting the LINEN bit in the CR2 register */
+ huart->Instance->CR2 |= USART_CR2_LINEN;
+
+ /* Set the USART LIN Break detection length. */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_LBDL, BreakDetectLength);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->State to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+
+/**
+ * @brief Initialize the multiprocessor mode according to the specified
+ * parameters in the UART_InitTypeDef and initialize the associated handle.
+ * @param huart: UART handle.
+ * @param Address: UART node address (4-, 6-, 7- or 8-bit long).
+ * @param WakeUpMethod: specifies the UART wakeup method.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_WAKEUPMETHOD_IDLELINE WakeUp by an idle line detection
+ * @arg @ref UART_WAKEUPMETHOD_ADDRESSMARK WakeUp by an address mark
+ * @note If the user resorts to idle line detection wake up, the Address parameter
+ * is useless and ignored by the initialization function.
+ * @note If the user resorts to address mark wake up, the address length detection
+ * is configured by default to 4 bits only. For the UART to be able to
+ * manage 6-, 7- or 8-bit long addresses detection, the API
+ * HAL_MultiProcessorEx_AddressLength_Set() must be called after
+ * HAL_MultiProcessor_Init().
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod)
+{
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the wake up method parameter */
+ assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod));
+
+ if(huart->State == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_UART_MspInit(huart);
+ }
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* In multiprocessor mode, the following bits must be kept cleared:
+ - LINEN and CLKEN bits in the USART_CR2 register,
+ - SCEN, HDSEL and IREN bits in the USART_CR3 register. */
+ huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN);
+ huart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN);
+
+ if (WakeUpMethod == UART_WAKEUPMETHOD_ADDRESSMARK)
+ {
+ /* If address mark wake up method is chosen, set the USART address node */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)Address << UART_CR2_ADDRESS_LSB_POS));
+ }
+
+ /* Set the wake up method by setting the WAKE bit in the CR1 register */
+ MODIFY_REG(huart->Instance->CR1, USART_CR1_WAKE, WakeUpMethod);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->State to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+
+
+/**
+ * @brief DeInitialize the UART peripheral.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
+{
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance)));
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ huart->Instance->CR1 = 0x0;
+ huart->Instance->CR2 = 0x0;
+ huart->Instance->CR3 = 0x0;
+
+ /* DeInit the low level hardware */
+ HAL_UART_MspDeInit(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->State = HAL_UART_STATE_RESET;
+
+ /* Process Unlock */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the UART MSP.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the UART MSP.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_MspDeInit can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group2 IO operation functions
+ * @brief UART Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ This subsection provides a set of functions allowing to manage the UART asynchronous
+ and Half duplex data transfers.
+
+ (#) There are two mode of transfer:
+ (+) Blocking mode: The communication is performed in polling mode.
+ The HAL status of all data processing is returned by the same function
+ after finishing transfer.
+ (+) No-Blocking mode: The communication is performed using Interrupts
+ or DMA, These API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated UART IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+ The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks
+ will be executed respectively at the end of the transmit or Receive process
+ The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected
+
+ (#) Blocking mode API's are :
+ (+) HAL_UART_Transmit()
+ (+) HAL_UART_Receive()
+
+ (#) Non-Blocking mode API's with Interrupt are :
+ (+) HAL_UART_Transmit_IT()
+ (+) HAL_UART_Receive_IT()
+ (+) HAL_UART_IRQHandler()
+
+ (#) No-Blocking mode API's with DMA are :
+ (+) HAL_UART_Transmit_DMA()
+ (+) HAL_UART_Receive_DMA()
+ (+) HAL_UART_DMAPause()
+ (+) HAL_UART_DMAResume()
+ (+) HAL_UART_DMAStop()
+
+ (#) A set of Transfer Complete Callbacks are provided in No_Blocking mode:
+ (+) HAL_UART_TxHalfCpltCallback()
+ (+) HAL_UART_TxCpltCallback()
+ (+) HAL_UART_RxHalfCpltCallback()
+ (+) HAL_UART_RxCpltCallback()
+ (+) HAL_UART_ErrorCallback()
+
+
+ -@- In the Half duplex communication, it is forbidden to run the transmit
+ and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send an amount of data in blocking mode.
+ * @param huart: UART handle.
+ * @param pData: Pointer to data buffer.
+ * @param Size: Amount of data to be sent.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint16_t* tmp;
+
+ if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_RX))
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ /* Check if a non-blocking receive process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX;
+ }
+
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+ while(huart->TxXferCount > 0)
+ {
+ huart->TxXferCount--;
+ if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ tmp = (uint16_t*) pData;
+ huart->Instance->TDR = (*tmp & (uint16_t)0x01FF);
+ pData += 2;
+ }
+ else
+ {
+ huart->Instance->TDR = (*pData++ & (uint8_t)0xFF);
+ }
+ }
+ if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ /* Check if a non-blocking receive Process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param huart: UART handle.
+ * @param pData: pointer to data buffer.
+ * @param Size: amount of data to be received.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint16_t* tmp;
+ uint16_t uhMask;
+
+ if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_TX))
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ /* Check if a non-blocking transmit process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_BUSY_RX;
+ }
+
+ huart->RxXferSize = Size;
+ huart->RxXferCount = Size;
+
+ /* Computation of UART mask to apply to RDR register */
+ UART_MASK_COMPUTATION(huart);
+ uhMask = huart->Mask;
+
+ /* as long as data have to be received */
+ while(huart->RxXferCount > 0)
+ {
+ huart->RxXferCount--;
+ if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ tmp = (uint16_t*) pData ;
+ *tmp = (uint16_t)(huart->Instance->RDR & uhMask);
+ pData +=2;
+ }
+ else
+ {
+ *pData++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
+ }
+ }
+
+ /* Check if a non-blocking transmit Process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_READY;
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @param huart: UART handle.
+ * @param pData: pointer to data buffer.
+ * @param Size: amount of data to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_RX))
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->pTxBuffPtr = pData;
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ /* Check if a receive process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ /* Enable the UART Transmit Data Register Empty Interrupt */
+ __HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @param huart: UART handle.
+ * @param pData: pointer to data buffer.
+ * @param Size: amount of data to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_TX))
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->pRxBuffPtr = pData;
+ huart->RxXferSize = Size;
+ huart->RxXferCount = Size;
+
+ /* Computation of UART mask to apply to RDR register */
+ UART_MASK_COMPUTATION(huart);
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ /* Check if a transmit process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_BUSY_RX;
+ }
+
+ /* Enable the UART Parity Error Interrupt */
+ __HAL_UART_ENABLE_IT(huart, UART_IT_PE);
+
+ /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ /* Enable the UART Data Register not empty Interrupt */
+ __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Send an amount of data in DMA mode.
+ * @param huart: UART handle.
+ * @param pData: pointer to data buffer.
+ * @param Size: amount of data to be sent.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ uint32_t *tmp;
+
+ if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_RX))
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->pTxBuffPtr = pData;
+ huart->TxXferSize = Size;
+ huart->TxXferCount = Size;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ /* Check if a receive process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX;
+ }
+
+ /* Set the UART DMA transfer complete callback */
+ huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
+
+ /* Set the UART DMA Half transfer complete callback */
+ huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
+
+ /* Set the DMA error callback */
+ huart->hdmatx->XferErrorCallback = UART_DMAError;
+
+ /* Enable the UART transmit DMA channel */
+ tmp = (uint32_t*)&pData;
+ HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t*)tmp, (uint32_t)&huart->Instance->TDR, Size);
+
+ /* Clear the TC flag in the ICR register */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_TCF);
+
+ /* Enable the DMA transfer for transmit request by setting the DMAT bit
+ in the UART CR3 register */
+ huart->Instance->CR3 |= USART_CR3_DMAT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in DMA mode.
+ * @param huart: UART handle.
+ * @param pData: pointer to data buffer.
+ * @param Size: amount of data to be received.
+ * @note When the UART parity is enabled (PCE = 1), the received data contain
+ * the parity bit (MSB position).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ uint32_t *tmp;
+
+ if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_TX))
+ {
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->pRxBuffPtr = pData;
+ huart->RxXferSize = Size;
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ /* Check if a transmit process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX_RX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_BUSY_RX;
+ }
+
+ /* Set the UART DMA transfer complete callback */
+ huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt;
+
+ /* Set the UART DMA Half transfer complete callback */
+ huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;
+
+ /* Set the DMA error callback */
+ huart->hdmarx->XferErrorCallback = UART_DMAError;
+
+ /* Enable the DMA channel */
+ tmp = (uint32_t*)&pData;
+ HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, *(uint32_t*)tmp, Size);
+
+ /* Enable the DMA transfer for the receiver request by setting the DMAR bit
+ in the UART CR3 register */
+ huart->Instance->CR3 |= USART_CR3_DMAR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Pause the DMA Transfer.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ if(huart->State == HAL_UART_STATE_BUSY_TX)
+ {
+ /* Disable the UART DMA Tx request */
+ huart->Instance->CR3 &= (uint32_t)(~USART_CR3_DMAT);
+ }
+ else if(huart->State == HAL_UART_STATE_BUSY_RX)
+ {
+ /* Disable the UART DMA Rx request */
+ huart->Instance->CR3 &= (uint32_t)(~USART_CR3_DMAR);
+ }
+ else if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ /* Disable the UART DMA Tx request */
+ huart->Instance->CR3 &= (uint32_t)(~USART_CR3_DMAT);
+ /* Disable the UART DMA Rx request */
+ huart->Instance->CR3 &= (uint32_t)(~USART_CR3_DMAR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the DMA Transfer.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ if(huart->State == HAL_UART_STATE_BUSY_TX)
+ {
+ /* Enable the UART DMA Tx request */
+ huart->Instance->CR3 |= USART_CR3_DMAT;
+ }
+ else if(huart->State == HAL_UART_STATE_BUSY_RX)
+ {
+ /* Clear the Overrun flag before resuming the Rx transfer */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+
+ /* Enable the UART DMA Rx request */
+ huart->Instance->CR3 |= USART_CR3_DMAR;
+ }
+ else if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ /* Clear the Overrun flag before resuming the Rx transfer */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+
+ /* Enable the UART DMA Rx request before the DMA Tx request */
+ huart->Instance->CR3 |= USART_CR3_DMAR;
+
+ /* Enable the UART DMA Tx request */
+ huart->Instance->CR3 |= USART_CR3_DMAT;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the DMA Transfer.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
+{
+ /* The Lock is not implemented on this API to allow the user application
+ to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() /
+ HAL_UART_TxHalfCpltCallback / HAL_UART_RxHalfCpltCallback:
+ indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete
+ interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of
+ the stream and the corresponding call back is executed. */
+
+ /* Disable the UART Tx/Rx DMA requests */
+ huart->Instance->CR3 &= ~USART_CR3_DMAT;
+ huart->Instance->CR3 &= ~USART_CR3_DMAR;
+
+ /* Abort the UART DMA tx channel */
+ if(huart->hdmatx != NULL)
+ {
+ HAL_DMA_Abort(huart->hdmatx);
+ }
+ /* Abort the UART DMA rx channel */
+ if(huart->hdmarx != NULL)
+ {
+ HAL_DMA_Abort(huart->hdmarx);
+ }
+
+ huart->State = HAL_UART_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle UART interrupt request.
+ * @param huart: UART handle.
+ * @retval None
+ */
+void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
+{
+ /* UART parity error interrupt occurred -------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_PE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE) != RESET))
+ {
+ __HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_PE;
+ /* Set the UART state ready to be able to start again the process */
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ /* UART frame error interrupt occurred --------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_FE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
+ {
+ __HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_FE;
+ /* Set the UART state ready to be able to start again the process */
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ /* UART noise error interrupt occurred --------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_NE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
+ {
+ __HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_NE;
+ /* Set the UART state ready to be able to start again the process */
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ /* UART Over-Run interrupt occurred -----------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_ORE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
+ {
+ __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF);
+
+ huart->ErrorCode |= HAL_UART_ERROR_ORE;
+ /* Set the UART state ready to be able to start again the process */
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ /* Call UART Error Call back function if need be --------------------------*/
+ if(huart->ErrorCode != HAL_UART_ERROR_NONE)
+ {
+ HAL_UART_ErrorCallback(huart);
+ }
+
+ /* UART wakeup from Stop mode interrupt occurred -------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_WUF) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_WUF) != RESET))
+ {
+ __HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF);
+ /* Set the UART state ready to be able to start again the process */
+ huart->State = HAL_UART_STATE_READY;
+ HAL_UARTEx_WakeupCallback(huart);
+ }
+
+ /* UART in mode Receiver ---------------------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) != RESET))
+ {
+ UART_Receive_IT(huart);
+ }
+
+
+ /* UART in mode Transmitter ------------------------------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE) != RESET))
+ {
+ UART_Transmit_IT(huart);
+ }
+
+ /* UART in mode Transmitter (transmission end) -----------------------------*/
+ if((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET))
+ {
+ UART_EndTransmit_IT(huart);
+ }
+
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_TxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Tx Half Transfer completed callback.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_UART_TxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_RxCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief Rx Half Transfer completed callback.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_UART_RxHalfCpltCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @brief UART error callback.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_ErrorCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions
+ * @brief UART control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the UART.
+ (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode
+ (+) HAL_MultiProcessor_DisableMuteMode() API disables mute mode
+ (+) HAL_MultiProcessor_EnterMuteMode() API enters mute mode
+ (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode
+ (+) UART_SetConfig() API configures the UART peripheral
+ (+) UART_AdvFeatureConfig() API optionally configures the UART advanced features
+ (+) UART_CheckIdleState() API ensures that TEACK and/or REACK are set after initialization
+ (+) UART_Wakeup_AddressConfig() API configures the wake-up from stop mode parameters
+ (+) HAL_HalfDuplex_EnableTransmitter() API disables receiver and enables transmitter
+ (+) HAL_HalfDuplex_EnableReceiver() API disables transmitter and enables receiver
+ (+) HAL_LIN_SendBreak() API transmits the break characters
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable UART in mute mode (does not mean UART enters mute mode;
+ * to enter mute mode, HAL_MultiProcessor_EnterMuteMode() API must be called).
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Enable USART mute mode by setting the MME bit in the CR1 register */
+ huart->Instance->CR1 |= USART_CR1_MME;
+
+ huart->State = HAL_UART_STATE_READY;
+
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Disable UART mute mode (does not mean the UART actually exits mute mode
+ * as it may not have been in mute mode at this very moment).
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable USART mute mode by clearing the MME bit in the CR1 register */
+ huart->Instance->CR1 &= ~(USART_CR1_MME);
+
+ huart->State = HAL_UART_STATE_READY;
+
+ return (UART_CheckIdleState(huart));
+}
+
+/**
+ * @brief Enter UART mute mode (means UART actually enters mute mode).
+ * @note To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called.
+ * @param huart: UART handle.
+ * @retval None
+ */
+void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart)
+{
+ __HAL_UART_SEND_REQ(huart, UART_MUTE_MODE_REQUEST);
+}
+
+/**
+ * @brief Enable the UART transmitter and disable the UART receiver.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Clear TE and RE bits */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
+ /* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */
+ SET_BIT(huart->Instance->CR1, USART_CR1_TE);
+
+ huart->State= HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the UART receiver and disable the UART transmitter.
+ * @param huart: UART handle.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Clear TE and RE bits */
+ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
+ /* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */
+ SET_BIT(huart->Instance->CR1, USART_CR1_RE);
+
+ huart->State = HAL_UART_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Transmit break characters.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart)
+{
+ /* Check the parameters */
+ assert_param(IS_UART_LIN_INSTANCE(huart->Instance));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Send break characters */
+ huart->Instance->RQR |= UART_SENDBREAK_REQUEST;
+
+ huart->State = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Error functions
+ * @brief UART Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State and Error functions #####
+ ==============================================================================
+ [..]
+ This subsection provides functions allowing to :
+ (+) Return the UART handle state.
+ (+) Return the UART handle error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the UART handle state.
+ * @param huart : pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART.
+ * @retval HAL state
+ */
+HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart)
+{
+ return huart->State;
+}
+
+/**
+* @brief Return the UART handle error code.
+* @param huart : pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART.
+* @retval UART Error Code
+*/
+uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart)
+{
+ return huart->ErrorCode;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup UART_Private_Functions UART Private Functions
+ * @{
+ */
+
+/**
+ * @brief Configure the UART peripheral.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart)
+{
+ uint32_t tmpreg = 0x00000000;
+ UART_ClockSourceTypeDef clocksource = UART_CLOCKSOURCE_UNDEFINED;
+ uint16_t brrtemp = 0x0000;
+ uint16_t usartdiv = 0x0000;
+ HAL_StatusTypeDef ret = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate));
+ assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
+ if(UART_INSTANCE_LOWPOWER(huart))
+ {
+ assert_param(IS_LPUART_STOPBITS(huart->Init.StopBits));
+ }
+ else
+ {
+ assert_param(IS_UART_STOPBITS(huart->Init.StopBits));
+ assert_param(IS_UART_ONE_BIT_SAMPLE(huart->Init.OneBitSampling));
+ }
+
+ assert_param(IS_UART_PARITY(huart->Init.Parity));
+ assert_param(IS_UART_MODE(huart->Init.Mode));
+ assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl));
+ assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
+
+
+ /*-------------------------- USART CR1 Configuration -----------------------*/
+ /* Clear M, PCE, PS, TE, RE and OVER8 bits and configure
+ * the UART Word Length, Parity, Mode and oversampling:
+ * set the M bits according to huart->Init.WordLength value
+ * set PCE and PS bits according to huart->Init.Parity value
+ * set TE and RE bits according to huart->Init.Mode value
+ * set OVER8 bit according to huart->Init.OverSampling value */
+ tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling ;
+ MODIFY_REG(huart->Instance->CR1, UART_CR1_FIELDS, tmpreg);
+
+ /*-------------------------- USART CR2 Configuration -----------------------*/
+ /* Configure the UART Stop Bits: Set STOP[13:12] bits according
+ * to huart->Init.StopBits value */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits);
+
+ /*-------------------------- USART CR3 Configuration -----------------------*/
+ /* Configure
+ * - UART HardWare Flow Control: set CTSE and RTSE bits according
+ * to huart->Init.HwFlowCtl value
+ * - one-bit sampling method versus three samples' majority rule according
+ * to huart->Init.OneBitSampling (not applicable to LPUART) */
+ tmpreg = (uint32_t)huart->Init.HwFlowCtl;
+ if (!(UART_INSTANCE_LOWPOWER(huart)))
+ {
+ tmpreg |= huart->Init.OneBitSampling;
+ }
+ MODIFY_REG(huart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT), tmpreg);
+
+ /*-------------------------- USART BRR Configuration -----------------------*/
+ UART_GETCLOCKSOURCE(huart, clocksource);
+
+ /* Check LPUART instance */
+ if(UART_INSTANCE_LOWPOWER(huart))
+ {
+ /* Retrieve frequency clock */
+ tmpreg = 0;
+
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_PCLK1:
+ tmpreg = HAL_RCC_GetPCLK1Freq();
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ tmpreg = (uint32_t) HSI_VALUE;
+ break;
+ case UART_CLOCKSOURCE_SYSCLK:
+ tmpreg = HAL_RCC_GetSysClockFreq();
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ tmpreg = (uint32_t) LSE_VALUE;
+ break;
+ case UART_CLOCKSOURCE_UNDEFINED:
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* if proper clock source reported */
+ if (tmpreg != 0)
+ {
+ /* ensure that Frequency clock is in the range [3 * baudrate, 4096 * baudrate] */
+ if ( (tmpreg < (3 * huart->Init.BaudRate) ) ||
+ (tmpreg > (4096 * huart->Init.BaudRate) ))
+ {
+ ret = HAL_ERROR;
+ }
+ else
+ {
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_PCLK1:
+ tmpreg = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ tmpreg = (uint32_t)(UART_DIV_LPUART(HSI_VALUE, huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_SYSCLK:
+ tmpreg = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ tmpreg = (uint32_t)(UART_DIV_LPUART(LSE_VALUE, huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_UNDEFINED:
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if ((tmpreg >= UART_LPUART_BRR_MIN) && (tmpreg <= UART_LPUART_BRR_MAX))
+ {
+ huart->Instance->BRR = tmpreg;
+ }
+ else
+ {
+ ret = HAL_ERROR;
+ }
+ } /* if ( (tmpreg < (3 * huart->Init.BaudRate) ) || (tmpreg > (4096 * huart->Init.BaudRate) )) */
+ } /* if (tmpreg != 0) */
+ }
+ /* Check UART Over Sampling to set Baud Rate Register */
+ else if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
+ {
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_PCLK1:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_PCLK2:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_SYSCLK:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ usartdiv = (uint16_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_UNDEFINED:
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ brrtemp = usartdiv & 0xFFF0;
+ brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000F) >> 1U);
+ huart->Instance->BRR = brrtemp;
+ }
+ else
+ {
+ switch (clocksource)
+ {
+ case UART_CLOCKSOURCE_PCLK1:
+ huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_PCLK2:
+ huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_HSI:
+ huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_SYSCLK:
+ huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_LSE:
+ huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate));
+ break;
+ case UART_CLOCKSOURCE_UNDEFINED:
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+ }
+
+ return ret;
+
+}
+
+/**
+ * @brief Configure the UART peripheral advanced features.
+ * @param huart: UART handle.
+ * @retval None
+ */
+void UART_AdvFeatureConfig(UART_HandleTypeDef *huart)
+{
+ /* Check whether the set of advanced features to configure is properly set */
+ assert_param(IS_UART_ADVFEATURE_INIT(huart->AdvancedInit.AdvFeatureInit));
+
+ /* if required, configure TX pin active level inversion */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_TXINVERT_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_TXINV(huart->AdvancedInit.TxPinLevelInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_TXINV, huart->AdvancedInit.TxPinLevelInvert);
+ }
+
+ /* if required, configure RX pin active level inversion */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXINVERT_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_RXINV(huart->AdvancedInit.RxPinLevelInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_RXINV, huart->AdvancedInit.RxPinLevelInvert);
+ }
+
+ /* if required, configure data inversion */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DATAINVERT_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_DATAINV(huart->AdvancedInit.DataInvert));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_DATAINV, huart->AdvancedInit.DataInvert);
+ }
+
+ /* if required, configure RX/TX pins swap */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_SWAP_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_SWAP(huart->AdvancedInit.Swap));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_SWAP, huart->AdvancedInit.Swap);
+ }
+
+ /* if required, configure RX overrun detection disabling */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXOVERRUNDISABLE_INIT))
+ {
+ assert_param(IS_UART_OVERRUN(huart->AdvancedInit.OverrunDisable));
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_OVRDIS, huart->AdvancedInit.OverrunDisable);
+ }
+
+ /* if required, configure DMA disabling on reception error */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DMADISABLEONERROR_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_DMAONRXERROR(huart->AdvancedInit.DMADisableonRxError));
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_DDRE, huart->AdvancedInit.DMADisableonRxError);
+ }
+
+ /* if required, configure auto Baud rate detection scheme */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT))
+ {
+ assert_param(IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(huart->Instance));
+ assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart->AdvancedInit.AutoBaudRateEnable));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN, huart->AdvancedInit.AutoBaudRateEnable);
+ /* set auto Baudrate detection parameters if detection is enabled */
+ if(huart->AdvancedInit.AutoBaudRateEnable == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE)
+ {
+ assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(huart->AdvancedInit.AutoBaudRateMode));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode);
+ }
+ }
+
+ /* if required, configure MSB first on communication line */
+ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_MSBFIRST_INIT))
+ {
+ assert_param(IS_UART_ADVFEATURE_MSBFIRST(huart->AdvancedInit.MSBFirst));
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_MSBFIRST, huart->AdvancedInit.MSBFirst);
+ }
+}
+
+/**
+ * @brief Check the UART Idle State.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart)
+{
+ /* Initialize the UART ErrorCode */
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+
+ /* Check if the Transmitter is enabled */
+ if((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE)
+ {
+ /* Wait until TEACK flag is set */
+ if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Check if the Receiver is enabled */
+ if((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE)
+ {
+ /* Wait until REACK flag is set */
+ if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ /* Timeout occurred */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Initialize the UART State */
+ huart->State= HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DMA UART transmit process complete callback.
+ * @param hdma: DMA handle.
+ * @retval None
+ */
+static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* DMA Normal mode */
+ if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
+ {
+ huart->TxXferCount = 0;
+
+ /* Disable the DMA transfer for transmit request by resetting the DMAT bit
+ in the UART CR3 register */
+ huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAT);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ __HAL_UART_ENABLE_IT(huart, UART_IT_TC);
+ }
+ /* DMA Circular mode */
+ else
+ {
+ HAL_UART_TxCpltCallback(huart);
+ }
+
+}
+
+/**
+ * @brief DMA UART transmit process half complete callback.
+ * @param hdma : DMA handle.
+ * @retval None
+ */
+static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef* huart = (UART_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ HAL_UART_TxHalfCpltCallback(huart);
+}
+
+/**
+ * @brief DMA UART receive process complete callback.
+ * @param hdma: DMA handle.
+ * @retval None
+ */
+static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* DMA Normal mode */
+ if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
+ {
+ huart->RxXferCount = 0;
+
+ /* Disable the DMA transfer for the receiver request by resetting the DMAR bit
+ in the UART CR3 register */
+ huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAR);
+
+ /* Check if a transmit Process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX;
+ }
+ else
+ {
+ huart->State = HAL_UART_STATE_READY;
+ }
+ }
+
+ HAL_UART_RxCpltCallback(huart);
+}
+
+/**
+ * @brief Handle UART Communication Timeout.
+ * @param huart: UART handle.
+ * @param Flag: specifies the UART flag to check.
+ * @param Status: the Flag status (SET or RESET).
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Wait until flag is set */
+ if(Status == RESET)
+ {
+ while(__HAL_UART_GET_FLAG(huart, Flag) == RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
+ __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
+ __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
+ __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
+
+ huart->State= HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_UART_GET_FLAG(huart, Flag) != RESET)
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
+ __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
+ __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
+ __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
+
+ huart->State= HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief DMA UART receive process half complete callback.
+ * @param hdma : DMA handle.
+ * @retval None
+ */
+static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef* huart = (UART_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ HAL_UART_RxHalfCpltCallback(huart);
+}
+
+/**
+ * @brief DMA UART communication error callback.
+ * @param hdma: DMA handle.
+ * @retval None
+ */
+static void UART_DMAError(DMA_HandleTypeDef *hdma)
+{
+ UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ huart->RxXferCount = 0;
+ huart->TxXferCount = 0;
+ huart->State= HAL_UART_STATE_READY;
+ huart->ErrorCode |= HAL_UART_ERROR_DMA;
+ HAL_UART_ErrorCallback(huart);
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Transmit_IT().
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
+{
+ uint16_t* tmp;
+
+ if ((huart->State == HAL_UART_STATE_BUSY_TX) || (huart->State == HAL_UART_STATE_BUSY_TX_RX))
+ {
+
+ if(huart->TxXferCount == 0)
+ {
+ /* Disable the UART Transmit Data Register Empty Interrupt */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
+
+ /* Enable the UART Transmit Complete Interrupt */
+ __HAL_UART_ENABLE_IT(huart, UART_IT_TC);
+
+ return HAL_OK;
+ }
+ else
+ {
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ tmp = (uint16_t*) huart->pTxBuffPtr;
+ huart->Instance->TDR = (*tmp & (uint16_t)0x01FF);
+ huart->pTxBuffPtr += 2;
+ }
+ else
+ {
+ huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFF);
+ }
+
+ huart->TxXferCount--;
+
+ return HAL_OK;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+
+/**
+ * @brief Wrap up transmission in non-blocking mode.
+ * @param huart: pointer to a UART_HandleTypeDef structure that contains
+ * the configuration information for the specified UART module.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
+{
+ /* Disable the UART Transmit Complete Interrupt */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_TC);
+
+ /* Check if a receive process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_RX;
+ }
+ else
+ {
+ /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
+
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ HAL_UART_TxCpltCallback(huart);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Receive an amount of data in interrupt mode.
+ * @note Function is called under interruption only, once
+ * interruptions have been enabled by HAL_UART_Receive_IT()
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
+{
+ uint16_t* tmp;
+ uint16_t uhMask = huart->Mask;
+
+ if((huart->State == HAL_UART_STATE_BUSY_RX) || (huart->State == HAL_UART_STATE_BUSY_TX_RX))
+ {
+
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ tmp = (uint16_t*) huart->pRxBuffPtr ;
+ *tmp = (uint16_t)(huart->Instance->RDR & uhMask);
+ huart->pRxBuffPtr +=2;
+ }
+ else
+ {
+ *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
+ }
+
+ if(--huart->RxXferCount == 0)
+ {
+ __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
+
+ /* Check if a transmit Process is ongoing or not */
+ if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
+ {
+ huart->State = HAL_UART_STATE_BUSY_TX;
+ }
+ else
+ {
+ /* Disable the UART Parity Error Interrupt */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
+
+ /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
+ __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
+
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ HAL_UART_RxCpltCallback(huart);
+
+ return HAL_OK;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Clear RXNE interrupt flag */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_UART_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_hal_uart_ex.c b/stmhal/hal/l4/src/stm32l4xx_hal_uart_ex.c
new file mode 100644
index 000000000..933f50c1c
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_hal_uart_ex.c
@@ -0,0 +1,462 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_hal_uart_ex.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief Extended UART HAL module driver.
+ * This file provides firmware functions to manage the following extended
+ * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ *
+ *
+ @verbatim
+ ==============================================================================
+ ##### UART peripheral extended features #####
+ ==============================================================================
+
+ (#) Declare a UART_HandleTypeDef handle structure.
+
+ (#) For the UART RS485 Driver Enable mode, initialize the UART registers
+ by calling the HAL_RS485Ex_Init() API.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup UARTEx UARTEx
+ * @brief UART Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_UART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup UARTEx_Private_Functions UARTEx Private Functions
+ * @{
+ */
+static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup UARTEx_Exported_Functions UARTEx Exported Functions
+ * @{
+ */
+
+/** @defgroup UARTEx_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Extended Initialization and Configuration Functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
+ in asynchronous mode.
+ (+) For the asynchronous mode the parameters below can be configured:
+ (++) Baud Rate
+ (++) Word Length
+ (++) Stop Bit
+ (++) Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ (++) Hardware flow control
+ (++) Receiver/transmitter modes
+ (++) Over Sampling Method
+ (++) One-Bit Sampling Method
+ (+) For the asynchronous mode, the following advanced features can be configured as well:
+ (++) TX and/or RX pin level inversion
+ (++) data logical level inversion
+ (++) RX and TX pins swap
+ (++) RX overrun detection disabling
+ (++) DMA disabling on RX error
+ (++) MSB first on communication line
+ (++) auto Baud rate detection
+ [..]
+ The HAL_RS485Ex_Init() API follows the UART RS485 mode configuration
+ procedures (details for the procedures are available in reference manual).
+
+@endverbatim
+
+ Depending on the frame length defined by the M1 and M0 bits (7-bit,
+ 8-bit or 9-bit), the possible UART formats are listed in the
+ following table.
+
+ Table 1. UART frame format.
+ +-----------------------------------------------------------------------+
+ | M1 bit | M0 bit | PCE bit | UART frame |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 0 | | SB | 7 bit data | STB | |
+ |---------|---------|-----------|---------------------------------------|
+ | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | |
+ +-----------------------------------------------------------------------+
+
+ * @{
+ */
+
+/**
+ * @brief Initialize the RS485 Driver enable feature according to the specified
+ * parameters in the UART_InitTypeDef and creates the associated handle.
+ * @param huart: UART handle.
+ * @param Polarity: select the driver enable polarity.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_DE_POLARITY_HIGH DE signal is active high
+ * @arg @ref UART_DE_POLARITY_LOW DE signal is active low
+ * @param AssertionTime: Driver Enable assertion time:
+ * 5-bit value defining the time between the activation of the DE (Driver Enable)
+ * signal and the beginning of the start bit. It is expressed in sample time
+ * units (1/8 or 1/16 bit time, depending on the oversampling rate)
+ * @param DeassertionTime: Driver Enable deassertion time:
+ * 5-bit value defining the time between the end of the last stop bit, in a
+ * transmitted message, and the de-activation of the DE (Driver Enable) signal.
+ * It is expressed in sample time units (1/8 or 1/16 bit time, depending on the
+ * oversampling rate).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime)
+{
+ uint32_t temp = 0x0;
+
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+ /* Check the Driver Enable UART instance */
+ assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance));
+
+ /* Check the Driver Enable polarity */
+ assert_param(IS_UART_DE_POLARITY(Polarity));
+
+ /* Check the Driver Enable assertion time */
+ assert_param(IS_UART_ASSERTIONTIME(AssertionTime));
+
+ /* Check the Driver Enable deassertion time */
+ assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime));
+
+ if(huart->State == HAL_UART_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ huart->Lock = HAL_UNLOCKED;
+
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX */
+ HAL_UART_MspInit(huart);
+ }
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
+ {
+ return HAL_ERROR;
+ }
+
+ if(huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ {
+ UART_AdvFeatureConfig(huart);
+ }
+
+ /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
+ SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
+
+ /* Set the Driver Enable polarity */
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
+
+ /* Set the Driver Enable assertion and deassertion times */
+ temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
+ temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
+ MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT|USART_CR1_DEAT), temp);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->State to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..] This section provides the following functions:
+ (+) HAL_UARTEx_EnableClockStopMode() API enables the UART clock (HSI or LSE only) during stop mode
+ (+) HAL_UARTEx_DisableClockStopMode() API disables the above functionality
+ (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address
+ detection length to more than 4 bits for multiprocessor address mark wake up.
+ (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode
+ trigger: address match, Start Bit detection or RXNE bit status.
+ (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode
+ (+) HAL_UARTEx_DisableStopMode() API disables the above functionality
+ (+) HAL_UARTEx_WakeupCallback() called upon UART wakeup interrupt
+
+
+@endverbatim
+ * @{
+ */
+
+
+
+
+/**
+ * @brief By default in multiprocessor mode, when the wake up method is set
+ * to address mark, the UART handles only 4-bit long addresses detection;
+ * this API allows to enable longer addresses detection (6-, 7- or 8-bit
+ * long).
+ * @note Addresses detection lengths are: 6-bit address detection in 7-bit data mode,
+ * 7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode.
+ * @param huart: UART handle.
+ * @param AddressLength: this parameter can be one of the following values:
+ * @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address
+ * @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength)
+{
+ /* Check the UART handle allocation */
+ if(huart == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the address length parameter */
+ assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength));
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the address length */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength);
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* TEACK and/or REACK to check before moving huart->State to Ready */
+ return (UART_CheckIdleState(huart));
+}
+
+
+/**
+ * @brief Set Wakeup from Stop mode interrupt flag selection.
+ * @param huart: UART handle.
+ * @param WakeUpSelection: address match, Start Bit detection or RXNE bit status.
+ * This parameter can be one of the following values:
+ * @arg @ref UART_WAKEUP_ON_ADDRESS
+ * @arg @ref UART_WAKEUP_ON_STARTBIT
+ * @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* check the wake-up from stop mode UART instance */
+ assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance));
+ /* check the wake-up selection parameter */
+ assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent));
+
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Disable the Peripheral */
+ __HAL_UART_DISABLE(huart);
+
+ /* Set the wake-up selection scheme */
+ MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent);
+
+ if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS)
+ {
+ UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_UART_ENABLE(huart);
+
+ /* Wait until REACK flag is set */
+ if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ status = HAL_TIMEOUT;
+ }
+ else
+ {
+ /* Initialize the UART State */
+ huart->State = HAL_UART_STATE_READY;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return status;
+}
+
+
+/**
+ * @brief Enable UART Stop Mode.
+ * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Set UESM bit */
+ SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
+
+ huart->State = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable UART Stop Mode.
+ * @param huart: UART handle.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart)
+{
+ /* Process Locked */
+ __HAL_LOCK(huart);
+
+ huart->State = HAL_UART_STATE_BUSY;
+
+ /* Clear UESM bit */
+ CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
+
+ huart->State = HAL_UART_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(huart);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief UART wakeup from Stop mode callback.
+ * @param huart: UART handle.
+ * @retval None
+ */
+__weak void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(huart);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UARTEx_WakeupCallback can be implemented in the user file.
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup UARTEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection.
+ * @param huart: UART handle.
+ * @param WakeUpSelection: UART wake up from stop mode parameters.
+ * @retval None
+ */
+static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
+{
+ assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength));
+
+ /* Set the USART address length */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength);
+
+ /* Set the USART address node */
+ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS));
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_UART_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_ll_sdmmc.c b/stmhal/hal/l4/src/stm32l4xx_ll_sdmmc.c
new file mode 100644
index 000000000..42e5ed7af
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_ll_sdmmc.c
@@ -0,0 +1,496 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_ll_sdmmc.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief SDMMC Low Layer HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the SDMMC peripheral:
+ * + Initialization/de-initialization functions
+ * + I/O operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### SDMMC peripheral features #####
+ ==============================================================================
+ [..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the APB2
+ peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA
+ devices.
+
+ [..] The SDMMC features include the following:
+ (+) Full compliance with MultiMedia Card System Specification Version 4.2. Card support
+ for three different data bus modes: 1-bit (default), 4-bit and 8-bit
+ (+) Full compatibility with previous versions of MultiMedia Cards (forward compatibility)
+ (+) Full compliance with SD Memory Card Specifications Version 2.0
+ (+) Full compliance with SD I/O Card Specification Version 2.0: card support for two
+ different data bus modes: 1-bit (default) and 4-bit
+ (+) Full support of the CE-ATA features (full compliance with CE-ATA digital protocol
+ Rev1.1)
+ (+) Data transfer up to 48 MHz for the 8 bit mode
+ (+) Data and command output enable signals to control external bidirectional drivers.
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a considered as a driver of service for external devices drivers
+ that interfaces with the SDMMC peripheral.
+ According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs
+ is used in the device's driver to perform SDMMC operations and functionalities.
+
+ This driver is almost transparent for the final user, it is only used to implement other
+ functionalities of the external device.
+
+ [..]
+ (+) The SDMMC clock (SDMMCCLK = 48 MHz) is coming from a specific output (MSI, PLLUSB1CLK,
+ PLLUSB2CLK). Before start working with SDMMC peripheral make sure that the
+ PLL is well configured.
+ The SDMMC peripheral uses two clock signals:
+ (++) SDMMC adapter clock (SDMMCCLK = 48 MHz)
+ (++) APB2 bus clock (PCLK2)
+
+ -@@- PCLK2 and SDMMC_CK clock frequencies must respect the following condition:
+ Frequency(PCLK2) >= (3 / 8 x Frequency(SDMMC_CK))
+
+ (+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC
+ peripheral.
+
+ (+) Enable the Power ON State using the SDMMC_PowerState_ON(SDMMCx)
+ function and disable it using the function SDMMC_PowerState_OFF(SDMMCx).
+
+ (+) Enable/Disable the clock using the __SDMMC_ENABLE()/__SDMMC_DISABLE() macros.
+
+ (+) Enable/Disable the peripheral interrupts using the macros __SDMMC_ENABLE_IT(hSDMMC, IT)
+ and __SDMMC_DISABLE_IT(hSDMMC, IT) if you need to use interrupt mode.
+
+ (+) When using the DMA mode
+ (++) Configure the DMA in the MSP layer of the external device
+ (++) Active the needed channel Request
+ (++) Enable the DMA using __SDMMC_DMA_ENABLE() macro or Disable it using the macro
+ __SDMMC_DMA_DISABLE().
+
+ (+) To control the CPSM (Command Path State Machine) and send
+ commands to the card use the SDMMC_SendCommand(SDMMCx),
+ SDMMC_GetCommandResponse() and SDMMC_GetResponse() functions. First, user has
+ to fill the command structure (pointer to SDMMC_CmdInitTypeDef) according
+ to the selected command to be sent.
+ The parameters that should be filled are:
+ (++) Command Argument
+ (++) Command Index
+ (++) Command Response type
+ (++) Command Wait
+ (++) CPSM Status (Enable or Disable).
+
+ -@@- To check if the command is well received, read the SDMMC_CMDRESP
+ register using the SDMMC_GetCommandResponse().
+ The SDMMC responses registers (SDMMC_RESP1 to SDMMC_RESP2), use the
+ SDMMC_GetResponse() function.
+
+ (+) To control the DPSM (Data Path State Machine) and send/receive
+ data to/from the card use the SDMMC_DataConfig(), SDMMC_GetDataCounter(),
+ SDMMC_ReadFIFO(), SDMMC_WriteFIFO() and SDMMC_GetFIFOCount() functions.
+
+ *** Read Operations ***
+ =======================
+ [..]
+ (#) First, user has to fill the data structure (pointer to
+ SDMMC_DataInitTypeDef) according to the selected data type to be received.
+ The parameters that should be filled are:
+ (++) Data TimeOut
+ (++) Data Length
+ (++) Data Block size
+ (++) Data Transfer direction: should be from card (To SDMMC)
+ (++) Data Transfer mode
+ (++) DPSM Status (Enable or Disable)
+
+ (#) Configure the SDMMC resources to receive the data from the card
+ according to selected transfer mode (Refer to Step 8, 9 and 10).
+
+ (#) Send the selected Read command (refer to step 11).
+
+ (#) Use the SDMMC flags/interrupts to check the transfer status.
+
+ *** Write Operations ***
+ ========================
+ [..]
+ (#) First, user has to fill the data structure (pointer to
+ SDMMC_DataInitTypeDef) according to the selected data type to be received.
+ The parameters that should be filled are:
+ (++) Data TimeOut
+ (++) Data Length
+ (++) Data Block size
+ (++) Data Transfer direction: should be to card (To CARD)
+ (++) Data Transfer mode
+ (++) DPSM Status (Enable or Disable)
+
+ (#) Configure the SDMMC resources to send the data to the card according to
+ selected transfer mode.
+
+ (#) Send the selected Write command.
+
+ (#) Use the SDMMC flags/interrupts to check the transfer status.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SDMMC_LL SDMMC Low Layer
+ * @brief Low layer module for SD
+ * @{
+ */
+
+#if defined (HAL_SD_MODULE_ENABLED)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
+ * @{
+ */
+
+/** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization/de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the SDMMC according to the specified
+ * parameters in the SDMMC_InitTypeDef and initialize the associated handle.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Init: SDMMC initialization structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_Init(SDMMC_TypeDef *SDMMCx, SDMMC_InitTypeDef Init)
+{
+ /* Check the parameters */
+ assert_param(IS_SDMMC_ALL_INSTANCE(SDMMCx));
+ assert_param(IS_SDMMC_CLOCK_EDGE(Init.ClockEdge));
+ assert_param(IS_SDMMC_CLOCK_BYPASS(Init.ClockBypass));
+ assert_param(IS_SDMMC_CLOCK_POWER_SAVE(Init.ClockPowerSave));
+ assert_param(IS_SDMMC_BUS_WIDE(Init.BusWide));
+ assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
+ assert_param(IS_SDMMC_CLKDIV(Init.ClockDiv));
+
+ /* Set SDMMC configuration parameters */
+ /* Write to SDMMC CLKCR */
+ MODIFY_REG(SDMMCx->CLKCR, CLKCR_CLEAR_MASK, Init.ClockEdge |\
+ Init.ClockBypass |\
+ Init.ClockPowerSave |\
+ Init.BusWide |\
+ Init.HardwareFlowControl |\
+ Init.ClockDiv);
+
+ return HAL_OK;
+}
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### I/O operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the SDMMC data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Read data (word) from Rx FIFO in blocking mode (polling)
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+uint32_t SDMMC_ReadFIFO(SDMMC_TypeDef *SDMMCx)
+{
+ /* Read data from Rx FIFO */
+ return (SDMMCx->FIFO);
+}
+
+/**
+ * @brief Write data (word) to Tx FIFO in blocking mode (polling)
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param pWriteData: pointer to data to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_WriteFIFO(SDMMC_TypeDef *SDMMCx, uint32_t *pWriteData)
+{
+ /* Write data to FIFO */
+ SDMMCx->FIFO = *pWriteData;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the SDMMC data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set SDMMC Power state to ON.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_PowerState_ON(SDMMC_TypeDef *SDMMCx)
+{
+ /* Set power state to ON */
+ SDMMCx->POWER = SDMMC_POWER_PWRCTRL;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set SDMMC Power state to OFF.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_PowerState_OFF(SDMMC_TypeDef *SDMMCx)
+{
+ /* Set power state to OFF */
+ SDMMCx->POWER = (uint32_t)0x00000000;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get SDMMC Power state.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Power status of the controller. The returned value can be one of the
+ * following values:
+ * - 0x00: Power OFF
+ * - 0x02: Power UP
+ * - 0x03: Power ON
+ */
+uint32_t SDMMC_GetPowerState(SDMMC_TypeDef *SDMMCx)
+{
+ return (SDMMCx->POWER & SDMMC_POWER_PWRCTRL);
+}
+
+/**
+ * @brief Configure the SDMMC command path according to the specified parameters in
+ * SDMMC_CmdInitTypeDef structure and send the command
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Command: pointer to a SDMMC_CmdInitTypeDef structure that contains
+ * the configuration information for the SDMMC command
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_SendCommand(SDMMC_TypeDef *SDMMCx, SDMMC_CmdInitTypeDef *Command)
+{
+ /* Check the parameters */
+ assert_param(IS_SDMMC_CMD_INDEX(Command->CmdIndex));
+ assert_param(IS_SDMMC_RESPONSE(Command->Response));
+ assert_param(IS_SDMMC_WAIT(Command->WaitForInterrupt));
+ assert_param(IS_SDMMC_CPSM(Command->CPSM));
+
+ /* Set the SDMMC Argument value */
+ SDMMCx->ARG = Command->Argument;
+
+ /* Set SDMMC command parameters */
+ /* Write to SDMMC CMD register */
+ MODIFY_REG(SDMMCx->CMD, CMD_CLEAR_MASK, Command->CmdIndex |\
+ Command->Response |\
+ Command->WaitForInterrupt |\
+ Command->CPSM);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Return the command index of last command for which response received
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Command index of the last command response received
+ */
+uint8_t SDMMC_GetCommandResponse(SDMMC_TypeDef *SDMMCx)
+{
+ return (uint8_t)(SDMMCx->RESPCMD);
+}
+
+
+/**
+ * @brief Return the response received from the card for the last command
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Response: Specifies the SDMMC response register.
+ * This parameter can be one of the following values:
+ * @arg SDMMC_RESP1: Response Register 1
+ * @arg SDMMC_RESP2: Response Register 2
+ * @arg SDMMC_RESP3: Response Register 3
+ * @arg SDMMC_RESP4: Response Register 4
+ * @retval The Corresponding response register value
+ */
+uint32_t SDMMC_GetResponse(SDMMC_TypeDef *SDMMCx, uint32_t Response)
+{
+ __IO uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SDMMC_RESP(Response));
+
+ /* Get the response */
+ tmp = (uint32_t)&(SDMMCx->RESP1) + Response;
+
+ return (*(__IO uint32_t *) tmp);
+}
+
+/**
+ * @brief Configure the SDMMC data path according to the specified
+ * parameters in the SDMMC_DataInitTypeDef.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param Data : pointer to a SDMMC_DataInitTypeDef structure
+ * that contains the configuration information for the SDMMC data.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef SDMMC_DataConfig(SDMMC_TypeDef *SDMMCx, SDMMC_DataInitTypeDef* Data)
+{
+ /* Check the parameters */
+ assert_param(IS_SDMMC_DATA_LENGTH(Data->DataLength));
+ assert_param(IS_SDMMC_BLOCK_SIZE(Data->DataBlockSize));
+ assert_param(IS_SDMMC_TRANSFER_DIR(Data->TransferDir));
+ assert_param(IS_SDMMC_TRANSFER_MODE(Data->TransferMode));
+ assert_param(IS_SDMMC_DPSM(Data->DPSM));
+
+ /* Set the SDMMC Data TimeOut value */
+ SDMMCx->DTIMER = Data->DataTimeOut;
+
+ /* Set the SDMMC DataLength value */
+ SDMMCx->DLEN = Data->DataLength;
+
+ /* Set the SDMMC data configuration parameters */
+ /* Write to SDMMC DCTRL */
+ MODIFY_REG(SDMMCx->DCTRL, DCTRL_CLEAR_MASK, Data->DataBlockSize |\
+ Data->TransferDir |\
+ Data->TransferMode |\
+ Data->DPSM);
+
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Returns number of remaining data bytes to be transferred.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Number of remaining data bytes to be transferred
+ */
+uint32_t SDMMC_GetDataCounter(SDMMC_TypeDef *SDMMCx)
+{
+ return (SDMMCx->DCOUNT);
+}
+
+/**
+ * @brief Get the FIFO data
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @retval Data received
+ */
+uint32_t SDMMC_GetFIFOCount(SDMMC_TypeDef *SDMMCx)
+{
+ return (SDMMCx->FIFO);
+}
+
+
+/**
+ * @brief Sets one of the two options of inserting read wait interval.
+ * @param SDMMCx: Pointer to SDMMC register base
+ * @param SDMMC_ReadWaitMode: SDMMC Read Wait operation mode.
+ * This parameter can be:
+ * @arg SDMMC_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
+ * @arg SDMMC_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
+ * @retval None
+ */
+HAL_StatusTypeDef SDMMC_SetSDMMCReadWaitMode(SDMMC_TypeDef *SDMMCx, uint32_t SDMMC_ReadWaitMode)
+{
+ /* Check the parameters */
+ assert_param(IS_SDMMC_READWAIT_MODE(SDMMC_ReadWaitMode));
+
+ /* Set SDMMC read wait mode */
+ MODIFY_REG(SDMMCx->DCTRL, SDMMC_DCTRL_RWMOD, SDMMC_ReadWaitMode);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* (HAL_SD_MODULE_ENABLED) */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/l4/src/stm32l4xx_ll_usb.c b/stmhal/hal/l4/src/stm32l4xx_ll_usb.c
new file mode 100644
index 000000000..db49163a7
--- /dev/null
+++ b/stmhal/hal/l4/src/stm32l4xx_ll_usb.c
@@ -0,0 +1,1630 @@
+/**
+ ******************************************************************************
+ * @file stm32l4xx_ll_usb.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 29-January-2016
+ * @brief USB Low Layer HAL module driver.
+ *
+ * This file provides firmware functions to manage the following
+ * functionalities of the USB Peripheral Controller:
+ * + Initialization/de-initialization functions
+ * + I/O operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Fill parameters of Init structure in USB_OTG_CfgTypeDef structure.
+
+ (#) Call USB_CoreInit() API to initialize the USB Core peripheral.
+
+ (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+#if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
+
+/** @addtogroup STM32L4xx_LL_USB_DRIVER
+ * @{
+ */
+
+#if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup LL_USB_Exported_Functions USB Low Layer Exported Functions
+ * @{
+ */
+
+/** @defgroup LL_USB_Group1 Initialization/de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization/de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the USB Core
+ * @param USBx: USB Instance
+ * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains
+ * the configuration information for the specified USBx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(cfg);
+
+ /* Select FS Embedded PHY */
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
+
+ /* Reset after a PHY select and set Host mode */
+ USB_CoreReset(USBx);
+
+ /* Deactivate the power down*/
+ USBx->GCCFG = USB_OTG_GCCFG_PWRDWN;
+
+ /* Enable srpcap*/
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_SRPCAP;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_EnableGlobalInt
+ * Enables the controller's Global Int in the AHB Config reg
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
+{
+ USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
+ return HAL_OK;
+}
+
+
+/**
+ * @brief USB_DisableGlobalInt
+ * Disable the controller's Global Int in the AHB Config reg
+ * @param USBx: Selected device
+ * @retval HAL status
+*/
+HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
+{
+ USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_SetCurrentMode : Set functional mode
+ * @param USBx: Selected device
+ * @param mode: current core mode
+ * This parameter can be one of these values:
+ * @arg USB_OTG_DEVICE_MODE: Peripheral mode
+ * @arg USB_OTG_HOST_MODE: Host mode
+ * @arg USB_OTG_DRD_MODE: Dual Role Device mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_OTG_ModeTypeDef mode)
+{
+ USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
+
+ if ( mode == USB_OTG_HOST_MODE)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
+ }
+ else if ( mode == USB_OTG_DEVICE_MODE)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
+ }
+ HAL_Delay(50);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DevInit : Initializes the USB_OTG controller registers
+ * for device mode
+ * @param USBx: Selected device
+ * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains
+ * the configuration information for the specified USBx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+ uint32_t i = 0;
+
+ /*Activate VBUS Sensing B */
+ USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
+
+ if (cfg.vbus_sensing_enable == 0)
+ {
+ /* Deactivate VBUS Sensing B */
+ USBx->GCCFG &= ~ USB_OTG_GCCFG_VBDEN;
+
+ /* B-peripheral session valid override enable*/
+ USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
+ USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
+ }
+
+ /* Restart the Phy Clock */
+ USBx_PCGCCTL = 0;
+
+ /* Device mode configuration */
+ USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80;
+
+ /* Set Full speed phy */
+ USB_SetDevSpeed (USBx , USB_OTG_SPEED_FULL);
+
+ /* Flush the FIFOs */
+ USB_FlushTxFifo(USBx , 0x10); /* all Tx FIFOs */
+ USB_FlushRxFifo(USBx);
+
+ /* Clear all pending Device Interrupts */
+ USBx_DEVICE->DIEPMSK = 0;
+ USBx_DEVICE->DOEPMSK = 0;
+ USBx_DEVICE->DAINT = 0xFFFFFFFF;
+ USBx_DEVICE->DAINTMSK = 0;
+
+ for (i = 0; i < cfg.dev_endpoints; i++)
+ {
+ if ((USBx_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+ {
+ USBx_INEP(i)->DIEPCTL = (USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK);
+ }
+ else
+ {
+ USBx_INEP(i)->DIEPCTL = 0;
+ }
+
+ USBx_INEP(i)->DIEPTSIZ = 0;
+ USBx_INEP(i)->DIEPINT = 0xFF;
+ }
+
+ for (i = 0; i < cfg.dev_endpoints; i++)
+ {
+ if ((USBx_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+ {
+ USBx_OUTEP(i)->DOEPCTL = (USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK);
+ }
+ else
+ {
+ USBx_OUTEP(i)->DOEPCTL = 0;
+ }
+
+ USBx_OUTEP(i)->DOEPTSIZ = 0;
+ USBx_OUTEP(i)->DOEPINT = 0xFF;
+ }
+
+ USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM);
+
+ if (cfg.dma_enable == 1)
+ {
+ /*Set threshold parameters */
+ USBx_DEVICE->DTHRCTL = (USB_OTG_DTHRCTL_TXTHRLEN_6 | USB_OTG_DTHRCTL_RXTHRLEN_6);
+ USBx_DEVICE->DTHRCTL |= (USB_OTG_DTHRCTL_RXTHREN | USB_OTG_DTHRCTL_ISOTHREN | USB_OTG_DTHRCTL_NONISOTHREN);
+
+ i= USBx_DEVICE->DTHRCTL;
+ }
+
+ /* Disable all interrupts. */
+ USBx->GINTMSK = 0;
+
+ /* Clear any pending interrupts */
+ USBx->GINTSTS = 0xBFFFFFFF;
+
+ /* Enable the common interrupts */
+ if (cfg.dma_enable == DISABLE)
+ {
+ USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
+ }
+
+ /* Enable interrupts matching to the Device mode ONLY */
+ USBx->GINTMSK |= (USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST |\
+ USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT |\
+ USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IISOIXFRM|\
+ USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM);
+
+ if(cfg.Sof_enable)
+ {
+ USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
+ }
+
+ if (cfg.vbus_sensing_enable == ENABLE)
+ {
+ USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT);
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief USB_OTG_FlushTxFifo : Flush a Tx FIFO
+ * @param USBx: Selected device
+ * @param num: FIFO number
+ * This parameter can be a value from 1 to 15
+ 15 means Flush all Tx FIFOs
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_FlushTxFifo (USB_OTG_GlobalTypeDef *USBx, uint32_t num )
+{
+ uint32_t count = 0;
+
+ USBx->GRSTCTL = ( USB_OTG_GRSTCTL_TXFFLSH |(uint32_t)( num << 6));
+
+ do
+ {
+ if (++count > 200000)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief USB_FlushRxFifo : Flush Rx FIFO
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t count = 0;
+
+ USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
+
+ do
+ {
+ if (++count > 200000)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_SetDevSpeed :Initializes the DevSpd field of DCFG register
+ * depending the PHY type and the enumeration speed of the device.
+ * @param USBx: Selected device
+ * @param speed: device speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @arg USB_OTG_SPEED_LOW: Low speed mode
+ * @retval Hal status
+ */
+HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx , uint8_t speed)
+{
+ USBx_DEVICE->DCFG |= speed;
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_GetDevSpeed :Return the Dev Speed
+ * @param USBx: Selected device
+ * @retval speed : device speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @arg USB_OTG_SPEED_LOW: Low speed mode
+ */
+uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint8_t speed = 0;
+
+ if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ)
+ {
+ speed = USB_OTG_SPEED_HIGH;
+ }
+ else if (((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ)||
+ ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_48MHZ))
+ {
+ speed = USB_OTG_SPEED_FULL;
+ }
+ else if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ)
+ {
+ speed = USB_OTG_SPEED_LOW;
+ }
+
+ return speed;
+}
+
+/**
+ * @brief Activate and configure an endpoint
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ if (ep->is_in == 1)
+ {
+ USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)));
+
+ if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0)
+ {
+ USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\
+ ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
+ }
+
+ }
+ else
+ {
+ USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16);
+
+ if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0)
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\
+ (USB_OTG_DIEPCTL_SD0PID_SEVNFRM)| (USB_OTG_DOEPCTL_USBAEP));
+ }
+ }
+ return HAL_OK;
+}
+/**
+ * @brief Activate and configure a dedicated endpoint
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ static __IO uint32_t debug = 0;
+
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1)
+ {
+ if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0)
+ {
+ USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\
+ ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
+ }
+
+
+ debug |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\
+ ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP));
+
+ USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)));
+ }
+ else
+ {
+ if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0)
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\
+ ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP));
+
+ debug = (uint32_t)(((uint32_t )USBx) + USB_OTG_OUT_ENDPOINT_BASE + (0)*USB_OTG_EP_REG_SIZE);
+ debug = (uint32_t )&USBx_OUTEP(ep->num)->DOEPCTL;
+ debug |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\
+ ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP));
+ }
+
+ USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16);
+ }
+
+ return HAL_OK;
+}
+/**
+ * @brief De-activate and de-initialize an endpoint
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1)
+ {
+ USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))));
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))));
+ USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
+ }
+ else
+ {
+ USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16));
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16));
+ USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief De-activate and de-initialize a dedicated endpoint
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1)
+ {
+ USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))));
+ }
+ else
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16));
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_EPStartXfer : setup and starts a transfer over an EP
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @param dma: USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma)
+{
+ uint16_t pktcnt = 0;
+
+ /* IN endpoint */
+ if (ep->is_in == 1)
+ {
+ /* Zero Length Packet? */
+ if (ep->xfer_len == 0)
+ {
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ;
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ }
+ else
+ {
+ /* Program the transfer size and packet count
+ * as follows: xfersize = N * maxpacket +
+ * short_packet pktcnt = N + (short_packet
+ * exist ? 1 : 0)
+ */
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (((ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket) << 19)) ;
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1 << 29));
+ }
+ }
+
+ if (dma == 1)
+ {
+ USBx_INEP(ep->num)->DIEPDMA = (uint32_t)(ep->dma_addr);
+ }
+ else
+ {
+ if (ep->type != EP_TYPE_ISOC)
+ {
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ {
+ USBx_DEVICE->DIEPEMPMSK |= 1 << ep->num;
+ }
+ }
+ }
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0)
+ {
+ USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
+ }
+ else
+ {
+ USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
+ }
+ }
+
+ /* EP enable, IN data in FIFO */
+ USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ USB_WritePacket(USBx, ep->xfer_buff, ep->num, ep->xfer_len, dma);
+ }
+ }
+ else /* OUT endpoint */
+ {
+ /* Program the transfer size and packet count as follows:
+ * pktcnt = N
+ * xfersize = N * maxpacket
+ */
+ USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
+ USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
+
+ if (ep->xfer_len == 0)
+ {
+ USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
+ USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ;
+ }
+ else
+ {
+ pktcnt = (ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket;
+ USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (pktcnt << 19)); ;
+ USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket * pktcnt));
+ }
+
+ if (dma == 1)
+ {
+ USBx_OUTEP(ep->num)->DOEPDMA = (uint32_t)ep->xfer_buff;
+ }
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0)
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
+ }
+ else
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
+ }
+ }
+ /* EP enable */
+ USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_EP0StartXfer : setup and starts a transfer over the EP 0
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @param dma: USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma)
+{
+ /* IN endpoint */
+ if (ep->is_in == 1)
+ {
+ /* Zero Length Packet? */
+ if (ep->xfer_len == 0)
+ {
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ;
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ }
+ else
+ {
+ /* Program the transfer size and packet count
+ * as follows: xfersize = N * maxpacket +
+ * short_packet pktcnt = N + (short_packet
+ * exist ? 1 : 0)
+ */
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+
+ if(ep->xfer_len > ep->maxpacket)
+ {
+ ep->xfer_len = ep->maxpacket;
+ }
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ;
+ USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
+
+ }
+
+ if (dma == 1)
+ {
+ USBx_INEP(ep->num)->DIEPDMA = (uint32_t)(ep->dma_addr);
+ }
+ else
+ {
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ {
+ USBx_DEVICE->DIEPEMPMSK |= 1 << (ep->num);
+ }
+ }
+
+ /* EP enable, IN data in FIFO */
+ USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+ }
+ else /* OUT endpoint */
+ {
+ /* Program the transfer size and packet count as follows:
+ * pktcnt = N
+ * xfersize = N * maxpacket
+ */
+ USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
+ USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
+
+ if (ep->xfer_len > 0)
+ {
+ ep->xfer_len = ep->maxpacket;
+ }
+
+ USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19));
+ USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket));
+
+
+ if (dma == 1)
+ {
+ USBx_OUTEP(ep->num)->DOEPDMA = (uint32_t)(ep->xfer_buff);
+ }
+
+ /* EP enable */
+ USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated
+ * with the EP/channel
+ * @param USBx: Selected device
+ * @param src: pointer to source buffer
+ * @param ch_ep_num: endpoint or host channel number
+ * @param len: Number of bytes to write
+ * @param dma: USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma)
+{
+ uint32_t count32b= 0 , i= 0;
+
+ if (dma == 0)
+ {
+ count32b = (len + 3) / 4;
+ for (i = 0; i < count32b; i++, src += 4)
+ {
+ USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src);
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_ReadPacket : read a packet from the Tx FIFO associated
+ * with the EP/channel
+ * @param USBx: Selected device
+ * @param src: source pointer
+ * @param ch_ep_num: endpoint or host channel number
+ * @param len: Number of bytes to read
+ * @param dma: USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval pointer to destination buffer
+ */
+void *USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
+{
+ uint32_t i=0;
+ uint32_t count32b = (len + 3) / 4;
+
+ for ( i = 0; i < count32b; i++, dest += 4 )
+ {
+ *(__packed uint32_t *)dest = USBx_DFIFO(0);
+
+ }
+ return ((void *)dest);
+}
+
+/**
+ * @brief USB_EPSetStall : set a stall condition over an EP
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep)
+{
+ if (ep->is_in == 1)
+ {
+ if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == 0)
+ {
+ USBx_INEP(ep->num)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS);
+ }
+ USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
+ }
+ else
+ {
+ if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == 0)
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS);
+ }
+ USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
+ }
+ return HAL_OK;
+}
+
+
+/**
+ * @brief USB_EPClearStall : Clear a stall condition over an EP
+ * @param USBx: Selected device
+ * @param ep: pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ if (ep->is_in == 1)
+ {
+ USBx_INEP(ep->num)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
+ if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK)
+ {
+ USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
+ }
+ }
+ else
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
+ if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK)
+ {
+ USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_StopDevice : Stop the USB device mode
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t i;
+
+ /* Clear Pending interrupt */
+ for (i = 0; i < 15 ; i++)
+ {
+ USBx_INEP(i)->DIEPINT = 0xFF;
+ USBx_OUTEP(i)->DOEPINT = 0xFF;
+ }
+ USBx_DEVICE->DAINT = 0xFFFFFFFF;
+
+ /* Clear interrupt masks */
+ USBx_DEVICE->DIEPMSK = 0;
+ USBx_DEVICE->DOEPMSK = 0;
+ USBx_DEVICE->DAINTMSK = 0;
+
+ /* Flush the FIFO */
+ USB_FlushRxFifo(USBx);
+ USB_FlushTxFifo(USBx , 0x10 );
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_SetDevAddress : Stop the USB device mode
+ * @param USBx: Selected device
+ * @param address: new device address to be assigned
+ * This parameter can be a value from 0 to 255
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_SetDevAddress (USB_OTG_GlobalTypeDef *USBx, uint8_t address)
+{
+ USBx_DEVICE->DCFG &= ~ (USB_OTG_DCFG_DAD);
+ USBx_DEVICE->DCFG |= (address << 4) & USB_OTG_DCFG_DAD ;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DevConnect : Connect the USB device by enabling the pull-up/pull-down
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevConnect (USB_OTG_GlobalTypeDef *USBx)
+{
+ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS ;
+ HAL_Delay(3);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx)
+{
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS ;
+ HAL_Delay(3);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_ReadInterrupts: return the global USB interrupt status
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+uint32_t USB_ReadInterrupts (USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t v = 0;
+
+ v = USBx->GINTSTS;
+ v &= USBx->GINTMSK;
+ return v;
+}
+
+/**
+ * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+uint32_t USB_ReadDevAllOutEpInterrupt (USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t v;
+ v = USBx_DEVICE->DAINT;
+ v &= USBx_DEVICE->DAINTMSK;
+ return ((v & 0xffff0000) >> 16);
+}
+
+/**
+ * @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+uint32_t USB_ReadDevAllInEpInterrupt (USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t v;
+ v = USBx_DEVICE->DAINT;
+ v &= USBx_DEVICE->DAINTMSK;
+ return ((v & 0xFFFF));
+}
+
+/**
+ * @brief Returns Device OUT EP Interrupt register
+ * @param USBx: Selected device
+ * @param epnum: endpoint number
+ * This parameter can be a value from 0 to 15
+ * @retval Device OUT EP Interrupt register
+ */
+uint32_t USB_ReadDevOutEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum)
+{
+ uint32_t v;
+ v = USBx_OUTEP(epnum)->DOEPINT;
+ v &= USBx_DEVICE->DOEPMSK;
+ return v;
+}
+
+/**
+ * @brief Returns Device IN EP Interrupt register
+ * @param USBx: Selected device
+ * @param epnum: endpoint number
+ * This parameter can be a value from 0 to 15
+ * @retval Device IN EP Interrupt register
+ */
+uint32_t USB_ReadDevInEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum)
+{
+ uint32_t v, msk, emp;
+
+ msk = USBx_DEVICE->DIEPMSK;
+ emp = USBx_DEVICE->DIEPEMPMSK;
+ msk |= ((emp >> epnum) & 0x1) << 7;
+ v = USBx_INEP(epnum)->DIEPINT & msk;
+ return v;
+}
+
+/**
+ * @brief USB_ClearInterrupts: clear a USB interrupt
+ * @param USBx: Selected device
+ * @param interrupt: interrupt flag
+ * @retval None
+ */
+void USB_ClearInterrupts (USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
+{
+ USBx->GINTSTS |= interrupt;
+}
+
+/**
+ * @brief Returns USB core mode
+ * @param USBx: Selected device
+ * @retval return core mode : Host or Device
+ * This parameter can be one of these values:
+ * 0 : Host
+ * 1 : Device
+ */
+uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx)
+{
+ return ((USBx->GINTSTS ) & 0x1);
+}
+
+
+/**
+ * @brief Activate EP0 for Setup transactions
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateSetup (USB_OTG_GlobalTypeDef *USBx)
+{
+ /* Set the MPS of the IN EP based on the enumeration speed */
+ USBx_INEP(0)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ;
+
+ if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ)
+ {
+ USBx_INEP(0)->DIEPCTL |= 3;
+ }
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Prepare the EP0 to start the first control setup
+ * @param USBx: Selected device
+ * @param dma: USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @param psetup: pointer to setup packet
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(psetup);
+
+ USBx_OUTEP(0)->DOEPTSIZ = 0;
+ USBx_OUTEP(0)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ;
+ USBx_OUTEP(0)->DOEPTSIZ |= (3 * 8);
+ USBx_OUTEP(0)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
+
+ if (dma == 1)
+ {
+ USBx_OUTEP(0)->DOEPDMA = (uint32_t)psetup;
+ /* EP enable */
+ USBx_OUTEP(0)->DOEPCTL = 0x80008000;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Reset the USB Core (needed after USB clock settings change)
+ * @param USBx: Selected device
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t count = 0;
+
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ if (++count > 200000)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
+
+ /* Core Soft Reset */
+ count = 0;
+ USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
+
+ do
+ {
+ if (++count > 200000)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief USB_HostInit : Initializes the USB OTG controller registers
+ * for Host mode
+ * @param USBx: Selected device
+ * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains
+ * the configuration information for the specified USBx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
+{
+ uint32_t i;
+
+ /* Restart the Phy Clock */
+ USBx_PCGCCTL = 0;
+
+ /*Activate VBUS Sensing B */
+ USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
+
+ /* Disable the FS/LS support mode only */
+ if((cfg.speed == USB_OTG_SPEED_FULL)&&
+ (USBx != USB_OTG_FS))
+ {
+ USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS;
+ }
+ else
+ {
+ USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
+ }
+
+ /* Make sure the FIFOs are flushed. */
+ USB_FlushTxFifo(USBx, 0x10 ); /* all Tx FIFOs */
+ USB_FlushRxFifo(USBx);
+
+ /* Clear all pending HC Interrupts */
+ for (i = 0; i < cfg.Host_channels; i++)
+ {
+ USBx_HC(i)->HCINT = 0xFFFFFFFF;
+ USBx_HC(i)->HCINTMSK = 0;
+ }
+
+ /* Enable VBUS driving */
+ USB_DriveVbus(USBx, 1);
+
+ HAL_Delay(200);
+
+ /* Disable all interrupts. */
+ USBx->GINTMSK = 0;
+
+ /* Clear any pending interrupts */
+ USBx->GINTSTS = 0xFFFFFFFF;
+
+ /* set Rx FIFO size */
+ USBx->GRXFSIZ = (uint32_t )0x80;
+ USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t )(((0x60 << 16)& USB_OTG_NPTXFD) | 0x80);
+ USBx->HPTXFSIZ = (uint32_t )(((0x40 << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0);
+
+ /* Enable the common interrupts */
+ if (cfg.dma_enable == DISABLE)
+ {
+ USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
+ }
+
+ /* Enable interrupts matching to the Host mode ONLY */
+ USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM | USB_OTG_GINTMSK_HCIM |\
+ USB_OTG_GINTMSK_SOFM |USB_OTG_GINTSTS_DISCINT|\
+ USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
+ * HCFG register on the PHY type and set the right frame interval
+ * @param USBx: Selected device
+ * @param freq: clock frequency
+ * This parameter can be one of these values:
+ * HCFG_48_MHZ : Full Speed 48 MHz Clock
+ * HCFG_6_MHZ : Low Speed 6 MHz Clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx , uint8_t freq)
+{
+ USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS);
+ USBx_HOST->HCFG |= (freq & USB_OTG_HCFG_FSLSPCS);
+
+ if (freq == HCFG_48_MHZ)
+ {
+ USBx_HOST->HFIR = (uint32_t)48000;
+ }
+ else if (freq == HCFG_6_MHZ)
+ {
+ USBx_HOST->HFIR = (uint32_t)6000;
+ }
+ return HAL_OK;
+}
+
+/**
+* @brief USB_OTG_ResetPort : Reset Host Port
+ * @param USBx: Selected device
+ * @retval HAL status
+ * @note (1)The application must wait at least 10 ms
+ * before clearing the reset bit.
+ */
+HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx)
+{
+ __IO uint32_t hprt0;
+
+ hprt0 = USBx_HPRT0;
+
+ hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
+ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
+
+ USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0);
+ HAL_Delay (10); /* See Note #1 */
+ USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0);
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DriveVbus : activate or de-activate vbus
+ * @param state: VBUS state
+ * This parameter can be one of these values:
+ * 0 : VBUS Active
+ * 1 : VBUS Inactive
+ * @retval HAL status
+*/
+HAL_StatusTypeDef USB_DriveVbus (USB_OTG_GlobalTypeDef *USBx, uint8_t state)
+{
+ __IO uint32_t hprt0;
+
+ hprt0 = USBx_HPRT0;
+ hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
+ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
+
+ if (((hprt0 & USB_OTG_HPRT_PPWR) == 0 ) && (state == 1 ))
+ {
+ USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0);
+ }
+ if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0 ))
+ {
+ USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Return Host Core speed
+ * @param USBx: Selected device
+ * @retval speed : Host speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @arg USB_OTG_SPEED_LOW: Low speed mode
+ */
+uint32_t USB_GetHostSpeed (USB_OTG_GlobalTypeDef *USBx)
+{
+ __IO uint32_t hprt0;
+
+ hprt0 = USBx_HPRT0;
+ return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17);
+}
+
+/**
+ * @brief Return Host Current Frame number
+ * @param USBx: Selected device
+ * @retval current frame number
+*/
+uint32_t USB_GetCurrentFrame (USB_OTG_GlobalTypeDef *USBx)
+{
+ return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
+}
+
+/**
+ * @brief Initialize a host channel
+ * @param USBx: Selected device
+ * @param ch_num : Channel number
+ * This parameter can be a value from 1 to 15
+ * @param epnum: Endpoint number
+ * This parameter can be a value from 1 to 15
+ * @param dev_address: Current device address
+ * This parameter can be a value from 0 to 255
+ * @param speed: Current device speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @arg USB_OTG_SPEED_LOW: Low speed mode
+ * @param ep_type: Endpoint Type
+ * This parameter can be one of these values:
+ * @arg EP_TYPE_CTRL: Control type
+ * @arg EP_TYPE_ISOC: Isochronous type
+ * @arg EP_TYPE_BULK: Bulk type
+ * @arg EP_TYPE_INTR: Interrupt type
+ * @param mps: Max Packet Size
+ * This parameter can be a value from 0 to32K
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx,
+ uint8_t ch_num,
+ uint8_t epnum,
+ uint8_t dev_address,
+ uint8_t speed,
+ uint8_t ep_type,
+ uint16_t mps)
+{
+
+ /* Clear old interrupt conditions for this host channel. */
+ USBx_HC(ch_num)->HCINT = 0xFFFFFFFF;
+
+ /* Enable channel interrupts required for this transfer. */
+ switch (ep_type)
+ {
+ case EP_TYPE_CTRL:
+ case EP_TYPE_BULK:
+
+ USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\
+ USB_OTG_HCINTMSK_STALLM |\
+ USB_OTG_HCINTMSK_TXERRM |\
+ USB_OTG_HCINTMSK_DTERRM |\
+ USB_OTG_HCINTMSK_AHBERR |\
+ USB_OTG_HCINTMSK_NAKM ;
+
+ if (epnum & 0x80)
+ {
+ USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
+ }
+ break;
+
+ case EP_TYPE_INTR:
+
+ USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\
+ USB_OTG_HCINTMSK_STALLM |\
+ USB_OTG_HCINTMSK_TXERRM |\
+ USB_OTG_HCINTMSK_DTERRM |\
+ USB_OTG_HCINTMSK_NAKM |\
+ USB_OTG_HCINTMSK_AHBERR |\
+ USB_OTG_HCINTMSK_FRMORM ;
+
+ if (epnum & 0x80)
+ {
+ USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
+ }
+
+ break;
+ case EP_TYPE_ISOC:
+
+ USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\
+ USB_OTG_HCINTMSK_ACKM |\
+ USB_OTG_HCINTMSK_AHBERR |\
+ USB_OTG_HCINTMSK_FRMORM ;
+
+ if (epnum & 0x80)
+ {
+ USBx_HC(ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM);
+ }
+ break;
+ }
+
+ /* Enable the top level host channel interrupt. */
+ USBx_HOST->HAINTMSK |= (1 << ch_num);
+
+ /* Make sure host channel interrupts are enabled. */
+ USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM;
+
+ /* Program the HCCHAR register */
+ USBx_HC(ch_num)->HCCHAR = (((dev_address << 22) & USB_OTG_HCCHAR_DAD) |\
+ (((epnum & 0x7F)<< 11) & USB_OTG_HCCHAR_EPNUM)|\
+ ((((epnum & 0x80) == 0x80)<< 15) & USB_OTG_HCCHAR_EPDIR)|\
+ (((speed == HPRT0_PRTSPD_LOW_SPEED)<< 17) & USB_OTG_HCCHAR_LSDEV)|\
+ ((ep_type << 18) & USB_OTG_HCCHAR_EPTYP)|\
+ (mps & USB_OTG_HCCHAR_MPSIZ));
+
+ if (ep_type == EP_TYPE_INTR)
+ {
+ USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM ;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Start a transfer over a host channel
+ * @param USBx: Selected device
+ * @param hc: pointer to host channel structure
+ * @param dma: USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL state
+ */
+#if defined (__CC_ARM) /*!< ARM Compiler */
+#pragma O0
+#elif defined (__GNUC__) /*!< GNU Compiler */
+#pragma GCC optimize ("O0")
+#endif /* __CC_ARM */
+HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma)
+{
+ uint8_t is_oddframe = 0;
+ uint16_t len_words = 0;
+ uint16_t num_packets = 0;
+ uint16_t max_hc_pkt_count = 256;
+ uint32_t tmpreg = 0;
+
+ /* Compute the expected number of packets associated to the transfer */
+ if (hc->xfer_len > 0)
+ {
+ num_packets = (hc->xfer_len + hc->max_packet - 1) / hc->max_packet;
+
+ if (num_packets > max_hc_pkt_count)
+ {
+ num_packets = max_hc_pkt_count;
+ hc->xfer_len = num_packets * hc->max_packet;
+ }
+ }
+ else
+ {
+ num_packets = 1;
+ }
+ if (hc->ep_is_in)
+ {
+ hc->xfer_len = num_packets * hc->max_packet;
+ }
+
+ /* Initialize the HCTSIZn register */
+ USBx_HC(hc->ch_num)->HCTSIZ = (((hc->xfer_len) & USB_OTG_HCTSIZ_XFRSIZ)) |\
+ ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\
+ (((hc->data_pid) << 29) & USB_OTG_HCTSIZ_DPID);
+
+ if (dma)
+ {
+ /* xfer_buff MUST be 32-bits aligned */
+ USBx_HC(hc->ch_num)->HCDMA = (uint32_t)hc->xfer_buff;
+ }
+
+ is_oddframe = (USBx_HOST->HFNUM & 0x01) ? 0 : 1;
+ USBx_HC(hc->ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
+ USBx_HC(hc->ch_num)->HCCHAR |= (is_oddframe << 29);
+
+ /* Set host channel enable */
+ tmpreg = USBx_HC(hc->ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hc->ch_num)->HCCHAR = tmpreg;
+
+ if (dma == 0) /* Slave mode */
+ {
+ if((hc->ep_is_in == 0) && (hc->xfer_len > 0))
+ {
+ switch(hc->ep_type)
+ {
+ /* Non periodic transfer */
+ case EP_TYPE_CTRL:
+ case EP_TYPE_BULK:
+
+ len_words = (hc->xfer_len + 3) / 4;
+
+ /* check if there is enough space in FIFO space */
+ if(len_words > (USBx->HNPTXSTS & 0xFFFF))
+ {
+ /* need to process data in nptxfempty interrupt */
+ USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM;
+ }
+ break;
+ /* Periodic transfer */
+ case EP_TYPE_INTR:
+ case EP_TYPE_ISOC:
+ len_words = (hc->xfer_len + 3) / 4;
+ /* check if there is enough space in FIFO space */
+ if(len_words > (USBx_HOST->HPTXSTS & 0xFFFF)) /* split the transfer */
+ {
+ /* need to process data in ptxfempty interrupt */
+ USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Write packet into the Tx FIFO. */
+ USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, hc->xfer_len, 0);
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read all host channel interrupts status
+ * @param USBx: Selected device
+ * @retval HAL state
+ */
+uint32_t USB_HC_ReadInterrupt (USB_OTG_GlobalTypeDef *USBx)
+{
+ return ((USBx_HOST->HAINT) & 0xFFFF);
+}
+
+/**
+ * @brief Halt a host channel
+ * @param USBx: Selected device
+ * @param hc_num: Host Channel number
+ * This parameter can be a value from 1 to 15
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx , uint8_t hc_num)
+{
+ uint32_t count = 0;
+
+ /* Check for space in the request queue to issue the halt. */
+ if (((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_CTRL << 18)) || ((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_BULK << 18)))
+ {
+ USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
+
+ if ((USBx->HNPTXSTS & 0xFFFF) == 0)
+ {
+ USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR;
+ do
+ {
+ if (++count > 1000)
+ {
+ break;
+ }
+ }
+ while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+ }
+ else
+ {
+ USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ }
+ }
+ else
+ {
+ USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
+
+ if ((USBx_HOST->HPTXSTS & 0xFFFF) == 0)
+ {
+ USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR;
+ do
+ {
+ if (++count > 1000)
+ {
+ break;
+ }
+ }
+ while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+ }
+ else
+ {
+ USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initiate Do Ping protocol
+ * @param USBx: Selected device
+ * @param hc_num: Host Channel number
+ * This parameter can be a value from 1 to 15
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx , uint8_t ch_num)
+{
+ uint8_t num_packets = 1;
+ uint32_t tmpreg = 0;
+
+ USBx_HC(ch_num)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\
+ USB_OTG_HCTSIZ_DOPING;
+
+ /* Set host channel enable */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop Host Core
+ * @param USBx: Selected device
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx)
+{
+ uint8_t i;
+ uint32_t count = 0;
+ uint32_t value;
+
+ USB_DisableGlobalInt(USBx);
+
+ /* Flush FIFO */
+ USB_FlushTxFifo(USBx, 0x10);
+ USB_FlushRxFifo(USBx);
+
+ /* Flush out any leftover queued requests. */
+ for (i = 0; i <= 15; i++)
+ {
+
+ value = USBx_HC(i)->HCCHAR ;
+ value |= USB_OTG_HCCHAR_CHDIS;
+ value &= ~USB_OTG_HCCHAR_CHENA;
+ value &= ~USB_OTG_HCCHAR_EPDIR;
+ USBx_HC(i)->HCCHAR = value;
+ }
+
+ /* Halt all channels to put them into a known state. */
+ for (i = 0; i <= 15; i++)
+ {
+ value = USBx_HC(i)->HCCHAR ;
+
+ value |= USB_OTG_HCCHAR_CHDIS;
+ value |= USB_OTG_HCCHAR_CHENA;
+ value &= ~USB_OTG_HCCHAR_EPDIR;
+
+ USBx_HC(i)->HCCHAR = value;
+ do
+ {
+ if (++count > 1000)
+ {
+ break;
+ }
+ }
+ while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+ }
+
+ /* Clear any pending Host interrupts */
+ USBx_HOST->HAINT = 0xFFFFFFFF;
+ USBx->GINTSTS = 0xFFFFFFFF;
+ USB_EnableGlobalInt(USBx);
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+#endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
+
+/**
+ * @}
+ */
+
+#endif /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/