summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/hal/f7/src
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/hal/f7/src')
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal.c504
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_adc.c1408
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_adc_ex.c854
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_can.c1435
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_cortex.c483
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_dac.c949
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_dac_ex.c376
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_dma.c921
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_flash.c817
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_flash_ex.c817
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_gpio.c540
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_i2c.c4110
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_i2s.c1535
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_pcd.c1202
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_pcd_ex.c197
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_pwr.c609
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_pwr_ex.c564
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_rcc.c1197
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_rcc_ex.c861
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_rng.c510
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_rtc.c1555
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_rtc_ex.c1813
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_sd.c3381
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_spi.c2728
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_tim.c5459
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_tim_ex.c2481
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_uart.c1996
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_ll_sdmmc.c510
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_ll_usb.c1696
29 files changed, 41508 insertions, 0 deletions
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal.c b/stmhal/hal/f7/src/stm32f7xx_hal.c
new file mode 100644
index 0000000000..7e123518b6
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal.c
@@ -0,0 +1,504 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup HAL HAL
+ * @brief HAL module driver.
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup HAL_Private_Constants
+ * @{
+ */
+/**
+ * @brief STM32F7xx HAL Driver version number V1.0.1
+ */
+#define __STM32F7xx_HAL_VERSION_MAIN (0x01) /*!< [31:24] main version */
+#define __STM32F7xx_HAL_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */
+#define __STM32F7xx_HAL_VERSION_SUB2 (0x01) /*!< [15:8] sub2 version */
+#define __STM32F7xx_HAL_VERSION_RC (0x00) /*!< [7:0] release candidate */
+#define __STM32F7xx_HAL_VERSION ((__STM32F7xx_HAL_VERSION_MAIN << 24)\
+ |(__STM32F7xx_HAL_VERSION_SUB1 << 16)\
+ |(__STM32F7xx_HAL_VERSION_SUB2 << 8 )\
+ |(__STM32F7xx_HAL_VERSION_RC))
+
+#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF)
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup HAL_Private_Variables
+ * @{
+ */
+static __IO uint32_t uwTick;
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private 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:
+ (+) Initializes the Flash interface the NVIC allocation and initial clock
+ configuration. It initializes the systick also when timeout is needed
+ and the backup domain when enabled.
+ (+) de-Initializes common part of the HAL
+ (+) Configure The time base source to have 1ms time base with a dedicated
+ Tick interrupt priority.
+ (++) Systick timer is used by default as source of time base, but user
+ can eventually implement his proper time base source (a general purpose
+ timer for example or other time source), keeping in mind that Time base
+ duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
+ handled in milliseconds basis.
+ (++) Time base configuration function (HAL_InitTick ()) is called automatically
+ at the beginning of the program after reset by HAL_Init() or at any time
+ when clock is configured, by HAL_RCC_ClockConfig().
+ (++) Source of time base is configured to generate interrupts at regular
+ time intervals. Care must be taken if HAL_Delay() is called from a
+ peripheral ISR process, the Tick interrupt line must have higher priority
+ (numerically lower) than the peripheral interrupt. Otherwise the caller
+ ISR process will be blocked.
+ (++) functions affecting time base configurations are declared as __weak
+ to make override possible in case of other implementations in user file.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function is used to initialize the HAL Library; it must be the first
+ * instruction to be executed in the main program (before to call any other
+ * HAL function), it performs the following:
+ * Configure the Flash prefetch, and instruction cache through ART accelerator.
+ * Configures the SysTick to generate an interrupt each 1 millisecond,
+ * which is clocked by the HSI (at this stage, the clock is not yet
+ * configured and thus the system is running from the internal HSI at 16 MHz).
+ * Set NVIC Group Priority to 4.
+ * Calls the HAL_MspInit() callback function defined in user file
+ * "stm32f7xx_hal_msp.c" to do the global low level hardware initialization
+ *
+ * @note SysTick is used as time base for the HAL_Delay() function, the application
+ * need to ensure that the SysTick time base is always set to 1 millisecond
+ * to have correct HAL operation.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_Init(void)
+{
+ /* Configure Flash prefetch and Instruction cache through ART accelerator */
+#if (ART_ACCLERATOR_ENABLE != 0)
+ __HAL_FLASH_ART_ENABLE();
+#endif /* ART_ACCLERATOR_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 HSI) */
+ HAL_InitTick(TICK_INT_PRIORITY);
+
+ /* Init the low level hardware */
+ HAL_MspInit();
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief This function de-Initializes common part of the HAL and stops the systick.
+ * 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 Initializes the MSP.
+ * @retval None
+ */
+__weak void HAL_MspInit(void)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the MSP.
+ * @retval None
+ */
+__weak void HAL_MspDeInit(void)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function configures the source of the time base.
+ * The time source is configured to have 1ms time base with a dedicated
+ * Tick interrupt priority.
+ * @note This function is called automatically at the beginning of program after
+ * reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig().
+ * @note In the default implementation, SysTick timer is the source of time base.
+ * It is used to generate interrupts at regular time intervals.
+ * Care must be taken if HAL_Delay() is called from a peripheral ISR process,
+ * The 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(HAL_RCC_GetHCLKFreq()/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
+ (+) Enable/Disable Debug module during SLEEP mode
+ (+) Enable/Disable Debug module during STOP mode
+ (+) Enable/Disable Debug module during STANDBY mode
+
+@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 Provides a tick value in millisecond.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval tick value
+ */
+__weak uint32_t HAL_GetTick(void)
+{
+ return uwTick;
+}
+
+/**
+ * @brief This function provides 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(__IO 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 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 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 Returns the HAL revision
+ * @retval version : 0xXYZR (8bits for each decimal, R for RC)
+ */
+uint32_t HAL_GetHalVersion(void)
+{
+ return __STM32F7xx_HAL_VERSION;
+}
+
+/**
+ * @brief Returns the device revision identifier.
+ * @retval Device revision identifier
+ */
+uint32_t HAL_GetREVID(void)
+{
+ return((DBGMCU->IDCODE) >> 16);
+}
+
+/**
+ * @brief Returns the device identifier.
+ * @retval Device identifier
+ */
+uint32_t HAL_GetDEVID(void)
+{
+ return((DBGMCU->IDCODE) & IDCODE_DEVID_MASK);
+}
+
+/**
+ * @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 STOP mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStopMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
+}
+
+/**
+ * @brief Disable the Debug Module during STOP mode
+ * @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);
+}
+
+/**
+ * @brief Enables the I/O Compensation Cell.
+ * @note The I/O compensation cell can be used only when the device supply
+ * voltage ranges from 2.4 to 3.6 V.
+ * @retval None
+ */
+void HAL_EnableCompensationCell(void)
+{
+ SYSCFG->CMPCR |= SYSCFG_CMPCR_CMP_PD;
+}
+
+/**
+ * @brief Power-down the I/O Compensation Cell.
+ * @note The I/O compensation cell can be used only when the device supply
+ * voltage ranges from 2.4 to 3.6 V.
+ * @retval None
+ */
+void HAL_DisableCompensationCell(void)
+{
+ SYSCFG->CMPCR &= (uint32_t)~((uint32_t)SYSCFG_CMPCR_CMP_PD);
+}
+
+/**
+ * @brief Enables the FMC Memory Mapping Swapping.
+ *
+ * @note SDRAM is accessible at 0x60000000
+ * and NOR/RAM is accessible at 0xC0000000
+ *
+ * @retval None
+ */
+void HAL_EnableFMCMemorySwapping(void)
+{
+ SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_0;
+}
+
+/**
+ * @brief Disables the FMC Memory Mapping Swapping
+ *
+ * @note SDRAM is accessible at 0xC0000000 (default mapping)
+ * and NOR/RAM is accessible at 0x60000000 (default mapping)
+ *
+ * @retval None
+ */
+void HAL_DisableFMCMemorySwapping(void)
+{
+
+ SYSCFG->MEMRMP &= (uint32_t)~((uint32_t)SYSCFG_MEMRMP_SWP_FMC);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_adc.c b/stmhal/hal/f7/src/stm32f7xx_hal_adc.c
new file mode 100644
index 0000000000..0c5f83b20c
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_adc.c
@@ -0,0 +1,1408 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_adc.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + State and errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### ADC Peripheral features #####
+ ==============================================================================
+ [..]
+ (#) 12-bit, 10-bit, 8-bit or 6-bit configurable resolution.
+ (#) Interrupt generation at the end of conversion, end of injected conversion,
+ and in case of analog watchdog or overrun events
+ (#) Single and continuous conversion modes.
+ (#) Scan mode for automatic conversion of channel 0 to channel x.
+ (#) Data alignment with in-built data coherency.
+ (#) Channel-wise programmable sampling time.
+ (#) External trigger option with configurable polarity for both regular and
+ injected conversion.
+ (#) Dual/Triple mode (on devices with 2 ADCs or more).
+ (#) Configurable DMA data storage in Dual/Triple ADC mode.
+ (#) Configurable delay between conversions in Dual/Triple interleaved mode.
+ (#) ADC conversion type (refer to the datasheets).
+ (#) ADC supply requirements: 2.4 V to 3.6 V at full speed and down to 1.8 V at
+ slower speed.
+ (#) ADC input range: VREF(minus) = VIN = VREF(plus).
+ (#) DMA request generation during regular channel conversion.
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#)Initialize the ADC low level resources by implementing the HAL_ADC_MspInit():
+ (##) Enable the ADC interface clock using __HAL_RCC_ADC_CLK_ENABLE()
+ (##) 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()
+ (##) In case of using interrupts (e.g. HAL_ADC_Start_IT())
+ (+++) Configure the ADC interrupt priority using HAL_NVIC_SetPriority()
+ (+++) Enable the ADC IRQ handler using HAL_NVIC_EnableIRQ()
+ (+++) In ADC IRQ handler, call HAL_ADC_IRQHandler()
+ (##) In case of using DMA to control data transfer (e.g. HAL_ADC_Start_DMA())
+ (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE()
+ (+++) Configure and enable two DMA streams stream for managing data
+ transfer from peripheral to memory (output stream)
+ (+++) Associate the initialized DMA handle to the CRYP DMA handle
+ using __HAL_LINKDMA()
+ (+++) Configure the priority and enable the NVIC for the transfer complete
+ interrupt on the two DMA Streams. The output stream should have higher
+ priority than the input stream.
+
+ *** Configuration of ADC, groups regular/injected, channels parameters ***
+ ==============================================================================
+ [..]
+ (#) Configure the ADC parameters (resolution, data alignment, ...)
+ and regular group parameters (conversion trigger, sequencer, ...)
+ using function HAL_ADC_Init().
+
+ (#) Configure the channels for regular group parameters (channel number,
+ channel rank into sequencer, ..., into regular group)
+ using function HAL_ADC_ConfigChannel().
+
+ (#) Optionally, configure the injected group parameters (conversion trigger,
+ sequencer, ..., of injected group)
+ and the channels for injected group parameters (channel number,
+ channel rank into sequencer, ..., into injected group)
+ using function HAL_ADCEx_InjectedConfigChannel().
+
+ (#) Optionally, configure the analog watchdog parameters (channels
+ monitored, thresholds, ...) using function HAL_ADC_AnalogWDGConfig().
+
+ (#) Optionally, for devices with several ADC instances: configure the
+ multimode parameters using function HAL_ADCEx_MultiModeConfigChannel().
+
+ *** Execution of ADC conversions ***
+ ==============================================================================
+ [..]
+ (#) ADC driver can be used among three modes: polling, interruption,
+ transfer by DMA.
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Start the ADC peripheral using HAL_ADC_Start()
+ (+) Wait for end of conversion using HAL_ADC_PollForConversion(), at this stage
+ user can specify the value of timeout according to his end application
+ (+) To read the ADC converted values, use the HAL_ADC_GetValue() function.
+ (+) Stop the ADC peripheral using HAL_ADC_Stop()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Start the ADC peripheral using HAL_ADC_Start_IT()
+ (+) Use HAL_ADC_IRQHandler() called under ADC_IRQHandler() Interrupt subroutine
+ (+) At ADC end of conversion HAL_ADC_ConvCpltCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADC_ConvCpltCallback
+ (+) In case of ADC Error, HAL_ADC_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADC_ErrorCallback
+ (+) Stop the ADC peripheral using HAL_ADC_Stop_IT()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Start the ADC peripheral using HAL_ADC_Start_DMA(), at this stage the user specify the length
+ of data to be transferred at each end of conversion
+ (+) At The end of data transfer by HAL_ADC_ConvCpltCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADC_ConvCpltCallback
+ (+) In case of transfer Error, HAL_ADC_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADC_ErrorCallback
+ (+) Stop the ADC peripheral using HAL_ADC_Stop_DMA()
+
+ *** ADC HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in ADC HAL driver.
+
+ (+) __HAL_ADC_ENABLE : Enable the ADC peripheral
+ (+) __HAL_ADC_DISABLE : Disable the ADC peripheral
+ (+) __HAL_ADC_ENABLE_IT: Enable the ADC end of conversion interrupt
+ (+) __HAL_ADC_DISABLE_IT: Disable the ADC end of conversion interrupt
+ (+) __HAL_ADC_GET_IT_SOURCE: Check if the specified ADC interrupt source is enabled or disabled
+ (+) __HAL_ADC_CLEAR_FLAG: Clear the ADC's pending flags
+ (+) __HAL_ADC_GET_FLAG: Get the selected ADC's flag status
+ (+) ADC_GET_RESOLUTION: Return resolution bits in CR1 register
+
+ [..]
+ (@) You can refer to the ADC HAL driver header file for more useful macros
+
+ *** Deinitialization of ADC ***
+ ==============================================================================
+ [..]
+ (#) Disable the ADC interface
+ (++) ADC clock can be hard reset and disabled at RCC top level.
+ (++) Hard reset of ADC peripherals
+ using macro __HAL_RCC_ADC_FORCE_RESET(), __HAL_RCC_ADC_RELEASE_RESET().
+ (++) ADC clock disable using the equivalent macro/functions as configuration step.
+ (+++) Example:
+ Into HAL_ADC_MspDeInit() (recommended code location) or with
+ other device clock parameters configuration:
+ (+++) HAL_RCC_GetOscConfig(&RCC_OscInitStructure);
+ (+++) RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI;
+ (+++) RCC_OscInitStructure.HSIState = RCC_HSI_OFF; (if not used for system clock)
+ (+++) HAL_RCC_OscConfig(&RCC_OscInitStructure);
+
+ (#) ADC pins configuration
+ (++) Disable the clock for the ADC GPIOs using macro __HAL_RCC_GPIOx_CLK_DISABLE()
+
+ (#) Optionally, in case of usage of ADC with interruptions:
+ (++) Disable the NVIC for ADC using function HAL_NVIC_DisableIRQ(ADCx_IRQn)
+
+ (#) Optionally, in case of usage of DMA:
+ (++) Deinitialize the DMA using function HAL_DMA_DeInit().
+ (++) Disable the NVIC for DMA using function HAL_NVIC_DisableIRQ(DMAx_Channelx_IRQn)
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup ADC ADC
+ * @brief ADC driver modules
+ * @{
+ */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup ADC_Private_Functions
+ * @{
+ */
+/* Private function prototypes -----------------------------------------------*/
+static void ADC_Init(ADC_HandleTypeDef* hadc);
+static void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma);
+static void ADC_DMAError(DMA_HandleTypeDef *hdma);
+static void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+
+/* 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 Initializes the ADCx peripheral according to the specified parameters
+ * in the ADC_InitStruct and initializes the ADC MSP.
+ *
+ * @note This function is used to configure the global features of the ADC (
+ * ClockPrescaler, Resolution, Data Alignment and number of conversion), however,
+ * the rest of the configuration parameters are specific to the regular
+ * channels group (scan mode activation, continuous mode activation,
+ * External trigger source and edge, DMA continuous request after the
+ * last transfer and End of conversion selection).
+ *
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc)
+{
+ /* 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_FUNCTIONAL_STATE(hadc->Init.ScanConvMode));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXT_TRIG(hadc->Init.ExternalTrigConv));
+ assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign));
+ assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests));
+ assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode));
+
+ if(hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
+ {
+ assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+ }
+
+ if(hadc->State == HAL_ADC_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hadc->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware */
+ HAL_ADC_MspInit(hadc);
+ }
+
+ /* Initialize the ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY;
+
+ /* Set ADC parameters */
+ ADC_Init(hadc);
+
+ /* Set ADC error code to none */
+ hadc->ErrorCode = HAL_ADC_ERROR_NONE;
+
+ /* Initialize the ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Deinitializes the ADCx peripheral registers to their default reset values.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @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 */
+ hadc->State = HAL_ADC_STATE_BUSY;
+
+ /* DeInit the low level hardware */
+ HAL_ADC_MspDeInit(hadc);
+
+ /* Set ADC error code to none */
+ hadc->ErrorCode = HAL_ADC_ERROR_NONE;
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_RESET;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the ADC MSP.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the ADC MSP.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group2 IO operation functions
+ * @brief IO operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion of regular channel.
+ (+) Stop conversion of regular channel.
+ (+) Start conversion of regular channel and enable interrupt.
+ (+) Stop conversion of regular channel and disable interrupt.
+ (+) Start conversion of regular channel and enable DMA transfer.
+ (+) Stop conversion of regular channel and disable DMA transfer.
+ (+) Handle ADC interrupt request.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables ADC and starts conversion of the regular channels.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
+{
+ __IO uint32_t counter = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Check if an injected conversion is ongoing */
+ if(hadc->State == HAL_ADC_STATE_BUSY_INJ)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_REG;
+ }
+
+ /* Check if ADC peripheral is disabled in order to enable it and wait during
+ Tstab time the ADC's stabilization */
+ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for ADC stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Check if Multimode enabled */
+ if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI))
+ {
+ /* if no external trigger present enable software conversion of regular channels */
+ if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)
+ {
+ /* Enable the selected ADC software conversion for regular group */
+ hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
+ }
+ }
+ else
+ {
+ /* if instance of handle correspond to ADC1 and no external trigger present enable software conversion of regular channels */
+ if((hadc->Instance == ADC1) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET))
+ {
+ /* Enable the selected ADC software conversion for regular group */
+ hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables ADC and stop conversion of regular channels.
+ *
+ * @note Caution: This function will stop also injected channels.
+ *
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ *
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc)
+{
+ /* Disable the Peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Poll for regular conversion complete
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param Timeout: Timeout value in millisecond.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Verification that ADC configuration is compliant with polling for */
+ /* each conversion: */
+ /* Particular case is ADC configured in DMA mode and ADC sequencer with */
+ /* several ranks and polling for end of each conversion. */
+ /* For code simplicity sake, this particular case is generalized to */
+ /* ADC configured in DMA mode and polling for end of each conversion. */
+ if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_EOCS) &&
+ HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_DMA) )
+ {
+ /* Update ADC state machine to error */
+ hadc->State = HAL_ADC_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ return HAL_ERROR;
+ }
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check End of conversion flag */
+ while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)))
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hadc->State= HAL_ADC_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check if an injected conversion is ready */
+ if(hadc->State == HAL_ADC_STATE_EOC_INJ)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_REG;
+ }
+
+ /* Return ADC state */
+ return HAL_OK;
+}
+
+/**
+ * @brief Poll for conversion event
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param EventType: the ADC event type.
+ * This parameter can be one of the following values:
+ * @arg ADC_AWD_EVENT: ADC Analog watch Dog event.
+ * @arg ADC_OVR_EVENT: ADC Overrun event.
+ * @param Timeout: Timeout value in millisecond.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_EVENT_TYPE(EventType));
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check selected event flag */
+ while(!(__HAL_ADC_GET_FLAG(hadc,EventType)))
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hadc->State= HAL_ADC_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check analog watchdog flag */
+ if(EventType == ADC_AWD_EVENT)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_AWD;
+
+ /* Clear the ADCx's analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_ERROR;
+
+ /* Clear the ADCx's Overrun flag */
+ __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
+ }
+
+ /* Return ADC state */
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Enables the interrupt and starts ADC conversion of regular channels.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)
+{
+ __IO uint32_t counter = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Check if an injected conversion is ongoing */
+ if(hadc->State == HAL_ADC_STATE_BUSY_INJ)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_REG;
+ }
+
+ /* Set ADC error code to none */
+ hadc->ErrorCode = HAL_ADC_ERROR_NONE;
+
+ /* Check if ADC peripheral is disabled in order to enable it and wait during
+ Tstab time the ADC's stabilization */
+ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for ADC stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+
+ /* Enable the ADC overrun interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Enable the ADC end of conversion interrupt for regular group */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOC);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Check if Multimode enabled */
+ if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI))
+ {
+ /* if no external trigger present enable software conversion of regular channels */
+ if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)
+ {
+ /* Enable the selected ADC software conversion for regular group */
+ hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
+ }
+ }
+ else
+ {
+ /* if instance of handle correspond to ADC1 and no external trigger present enable software conversion of regular channels */
+ if((hadc->Instance == (ADC_TypeDef*)0x40012000) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET))
+ {
+ /* Enable the selected ADC software conversion for regular group */
+ hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables the interrupt and stop ADC conversion of regular channels.
+ *
+ * @note Caution: This function will stop also injected channels.
+ *
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc)
+{
+ /* Disable the ADC end of conversion interrupt for regular group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
+
+ /* Disable the ADC end of conversion interrupt for injected group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_CR1_JEOCIE);
+
+ /* Enable the Peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles ADC interrupt request
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
+{
+ uint32_t tmp1 = 0, tmp2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion));
+ assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection));
+
+ tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC);
+ tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_EOC);
+ /* Check End of conversion flag for regular channels */
+ if(tmp1 && tmp2)
+ {
+ /* Check if an injected conversion is ready */
+ if(hadc->State == HAL_ADC_STATE_EOC_INJ)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_REG;
+ }
+
+ if((hadc->Init.ContinuousConvMode == DISABLE) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET))
+ {
+ if(hadc->Init.EOCSelection == ADC_EOC_SEQ_CONV)
+ {
+ /* DISABLE the ADC end of conversion interrupt for regular group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
+
+ /* DISABLE the ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+ }
+ else
+ {
+ if (hadc->NbrOfCurrentConversionRank == 0)
+ {
+ hadc->NbrOfCurrentConversionRank = hadc->Init.NbrOfConversion;
+ }
+
+ /* Decrement the number of conversion when an interrupt occurs */
+ hadc->NbrOfCurrentConversionRank--;
+
+ /* Check if all conversions are finished */
+ if(hadc->NbrOfCurrentConversionRank == 0)
+ {
+ /* DISABLE the ADC end of conversion interrupt for regular group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
+
+ /* DISABLE the ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+ }
+ }
+ }
+
+ /* Conversion complete callback */
+ HAL_ADC_ConvCpltCallback(hadc);
+
+ /* Clear the ADCx flag for regular end of conversion */
+ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_EOC);
+ }
+
+ tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC);
+ tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_JEOC);
+ /* Check End of conversion flag for injected channels */
+ if(tmp1 && tmp2)
+ {
+ /* Check if a regular conversion is ready */
+ if(hadc->State == HAL_ADC_STATE_EOC_REG)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ;
+ }
+
+ tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
+ tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
+ if(((hadc->Init.ContinuousConvMode == DISABLE) || tmp1) && tmp2)
+ {
+ /* DISABLE the ADC end of conversion interrupt for injected group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
+ }
+
+ /* Conversion complete callback */
+ HAL_ADCEx_InjectedConvCpltCallback(hadc);
+
+ /* Clear the ADCx flag for injected end of conversion */
+ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_JEOC);
+ }
+
+ tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_AWD);
+ tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_AWD);
+ /* Check Analog watchdog flag */
+ if(tmp1 && tmp2)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_AWD;
+
+ /* Clear the ADCx's Analog watchdog flag */
+ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_AWD);
+
+ /* Level out of window callback */
+ HAL_ADC_LevelOutOfWindowCallback(hadc);
+ }
+
+ tmp1 = __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_OVR);
+ tmp2 = __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_OVR);
+ /* Check Overrun flag */
+ if(tmp1 && tmp2)
+ {
+ /* Change ADC state to overrun state */
+ hadc->State = HAL_ADC_STATE_ERROR;
+
+ /* Set ADC error code to overrun */
+ hadc->ErrorCode |= HAL_ADC_ERROR_OVR;
+
+ /* Clear the Overrun flag */
+ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_OVR);
+
+ /* Error callback */
+ HAL_ADC_ErrorCallback(hadc);
+ }
+}
+
+/**
+ * @brief Enables ADC DMA request after last transfer (Single-ADC mode) and enables ADC peripheral
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param pData: The destination Buffer address.
+ * @param Length: The length of data to be transferred from ADC peripheral to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
+{
+ __IO uint32_t counter = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable ADC overrun interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Enable ADC DMA mode */
+ hadc->Instance->CR2 |= ADC_CR2_DMA;
+
+ /* 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 ;
+
+ /* Enable the DMA Stream */
+ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_REG;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Check if ADC peripheral is disabled in order to enable it and wait during
+ Tstab time the ADC's stabilization */
+ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for ADC stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+
+ /* if no external trigger present enable software conversion of regular channels */
+ if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)
+ {
+ /* Enable the selected ADC software conversion for regular group */
+ hadc->Instance->CR2 |= ADC_CR2_SWSTART;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables ADC DMA (Single-ADC mode) and disables ADC peripheral
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc)
+{
+ /* Disable the Peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Disable the selected ADC DMA mode */
+ hadc->Instance->CR2 &= ~ADC_CR2_DMA;
+
+ /* Disable the ADC DMA Stream */
+ HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets the converted value from data register of regular channel.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval Converted value
+ */
+uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)
+{
+ /* Return the selected ADC converted value */
+ return hadc->Instance->DR;
+}
+
+/**
+ * @brief Regular conversion complete callback in non blocking mode
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_ConvCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Regular conversion half DMA transfer callback in non blocking mode
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_ConvHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Analog watchdog callback in non blocking mode
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_LevelOoutOfWindowCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Error ADC callback.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_ErrorCallback could 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 regular channels.
+ (+) Configure injected channels.
+ (+) Configure multimode.
+ (+) Configure the analog watch dog.
+
+@endverbatim
+ * @{
+ */
+
+ /**
+ * @brief Configures for the selected ADC regular channel its corresponding
+ * rank in the sequencer and its sample time.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param sConfig: ADC configuration structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
+{
+ __IO uint32_t counter = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_CHANNEL(sConfig->Channel));
+ assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
+ assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* if ADC_Channel_10 ... ADC_Channel_18 is selected */
+ if (sConfig->Channel > ADC_CHANNEL_9)
+ {
+ /* Clear the old sample time */
+ hadc->Instance->SMPR1 &= ~ADC_SMPR1(ADC_SMPR1_SMP10, sConfig->Channel);
+
+ /* Set the new sample time */
+ hadc->Instance->SMPR1 |= ADC_SMPR1(sConfig->SamplingTime, sConfig->Channel);
+ }
+ else /* ADC_Channel include in ADC_Channel_[0..9] */
+ {
+ /* Clear the old sample time */
+ hadc->Instance->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, sConfig->Channel);
+
+ /* Set the new sample time */
+ hadc->Instance->SMPR2 |= ADC_SMPR2(sConfig->SamplingTime, sConfig->Channel);
+ }
+
+ /* For Rank 1 to 6 */
+ if (sConfig->Rank < 7)
+ {
+ /* Clear the old SQx bits for the selected rank */
+ hadc->Instance->SQR3 &= ~ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank);
+
+ /* Set the SQx bits for the selected rank */
+ hadc->Instance->SQR3 |= ADC_SQR3_RK(sConfig->Channel, sConfig->Rank);
+ }
+ /* For Rank 7 to 12 */
+ else if (sConfig->Rank < 13)
+ {
+ /* Clear the old SQx bits for the selected rank */
+ hadc->Instance->SQR2 &= ~ADC_SQR2_RK(ADC_SQR2_SQ7, sConfig->Rank);
+
+ /* Set the SQx bits for the selected rank */
+ hadc->Instance->SQR2 |= ADC_SQR2_RK(sConfig->Channel, sConfig->Rank);
+ }
+ /* For Rank 13 to 16 */
+ else
+ {
+ /* Clear the old SQx bits for the selected rank */
+ hadc->Instance->SQR1 &= ~ADC_SQR1_RK(ADC_SQR1_SQ13, sConfig->Rank);
+
+ /* Set the SQx bits for the selected rank */
+ hadc->Instance->SQR1 |= ADC_SQR1_RK(sConfig->Channel, sConfig->Rank);
+ }
+
+ /* if ADC1 Channel_18 is selected enable VBAT Channel */
+ if ((hadc->Instance == ADC1) && (sConfig->Channel == ADC_CHANNEL_VBAT))
+ {
+ /* Enable the VBAT channel*/
+ ADC->CCR |= ADC_CCR_VBATE;
+ }
+
+ /* if ADC1 Channel_16 or Channel_17 is selected enable TSVREFE Channel(Temperature sensor and VREFINT) */
+ if ((hadc->Instance == ADC1) && ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) || (sConfig->Channel == ADC_CHANNEL_VREFINT)))
+ {
+ /* Enable the TSVREFE channel*/
+ ADC->CCR |= ADC_CCR_TSVREFE;
+
+ if((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR))
+ {
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the analog watchdog.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param AnalogWDGConfig : pointer to an ADC_AnalogWDGConfTypeDef structure
+ * that contains the configuration information of ADC analog watchdog.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef* hadc, ADC_AnalogWDGConfTypeDef* AnalogWDGConfig)
+{
+#ifdef USE_FULL_ASSERT
+ uint32_t tmp = 0;
+#endif /* USE_FULL_ASSERT */
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ANALOG_WATCHDOG(AnalogWDGConfig->WatchdogMode));
+ assert_param(IS_ADC_CHANNEL(AnalogWDGConfig->Channel));
+ assert_param(IS_FUNCTIONAL_STATE(AnalogWDGConfig->ITMode));
+
+#ifdef USE_FULL_ASSERT
+ tmp = ADC_GET_RESOLUTION(hadc);
+ assert_param(IS_ADC_RANGE(tmp, AnalogWDGConfig->HighThreshold));
+ assert_param(IS_ADC_RANGE(tmp, AnalogWDGConfig->LowThreshold));
+#endif /* USE_FULL_ASSERT */
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ if(AnalogWDGConfig->ITMode == ENABLE)
+ {
+ /* Enable the ADC Analog watchdog interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_AWD);
+ }
+ else
+ {
+ /* Disable the ADC Analog watchdog interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD);
+ }
+
+ /* Clear AWDEN, JAWDEN and AWDSGL bits */
+ hadc->Instance->CR1 &= ~(ADC_CR1_AWDSGL | ADC_CR1_JAWDEN | ADC_CR1_AWDEN);
+
+ /* Set the analog watchdog enable mode */
+ hadc->Instance->CR1 |= AnalogWDGConfig->WatchdogMode;
+
+ /* Set the high threshold */
+ hadc->Instance->HTR = AnalogWDGConfig->HighThreshold;
+
+ /* Set the low threshold */
+ hadc->Instance->LTR = AnalogWDGConfig->LowThreshold;
+
+ /* Clear the Analog watchdog channel select bits */
+ hadc->Instance->CR1 &= ~ADC_CR1_AWDCH;
+
+ /* Set the Analog watchdog channel */
+ hadc->Instance->CR1 |= (uint32_t)((uint16_t)(AnalogWDGConfig->Channel));
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Exported_Functions_Group4 ADC Peripheral State functions
+ * @brief ADC Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the ADC state
+ (+) Check the ADC Error
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief return the ADC state
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL state
+ */
+HAL_ADC_StateTypeDef HAL_ADC_GetState(ADC_HandleTypeDef* hadc)
+{
+ /* Return ADC state */
+ return hadc->State;
+}
+
+/**
+ * @brief Return the ADC error code
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval ADC Error Code
+ */
+uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc)
+{
+ return hadc->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup ADC_Private_Functions ADC Private Functions
+ * @{
+ */
+
+/**
+ * @brief Initializes the ADCx peripheral according to the specified parameters
+ * in the ADC_InitStruct without initializing the ADC MSP.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+static void ADC_Init(ADC_HandleTypeDef* hadc)
+{
+ /* Set ADC parameters */
+ /* Set the ADC clock prescaler */
+ ADC->CCR &= ~(ADC_CCR_ADCPRE);
+ ADC->CCR |= hadc->Init.ClockPrescaler;
+
+ /* Set ADC scan mode */
+ hadc->Instance->CR1 &= ~(ADC_CR1_SCAN);
+ hadc->Instance->CR1 |= ADC_CR1_SCANCONV(hadc->Init.ScanConvMode);
+
+ /* Set ADC resolution */
+ hadc->Instance->CR1 &= ~(ADC_CR1_RES);
+ hadc->Instance->CR1 |= hadc->Init.Resolution;
+
+ /* Set ADC data alignment */
+ hadc->Instance->CR2 &= ~(ADC_CR2_ALIGN);
+ hadc->Instance->CR2 |= hadc->Init.DataAlign;
+
+ /* Enable external trigger if trigger selection is different of software */
+ /* start. */
+ /* Note: This configuration keeps the hardware feature of parameter */
+ /* ExternalTrigConvEdge "trigger edge none" equivalent to */
+ /* software start. */
+ if(hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START)
+ {
+ /* Select external trigger to start conversion */
+ hadc->Instance->CR2 &= ~(ADC_CR2_EXTSEL);
+ hadc->Instance->CR2 |= hadc->Init.ExternalTrigConv;
+
+ /* Select external trigger polarity */
+ hadc->Instance->CR2 &= ~(ADC_CR2_EXTEN);
+ hadc->Instance->CR2 |= hadc->Init.ExternalTrigConvEdge;
+ }
+ else
+ {
+ /* Reset the external trigger */
+ hadc->Instance->CR2 &= ~(ADC_CR2_EXTSEL);
+ hadc->Instance->CR2 &= ~(ADC_CR2_EXTEN);
+ }
+
+ /* Enable or disable ADC continuous conversion mode */
+ hadc->Instance->CR2 &= ~(ADC_CR2_CONT);
+ hadc->Instance->CR2 |= ADC_CR2_CONTINUOUS(hadc->Init.ContinuousConvMode);
+
+ if(hadc->Init.DiscontinuousConvMode != DISABLE)
+ {
+ assert_param(IS_ADC_REGULAR_DISC_NUMBER(hadc->Init.NbrOfDiscConversion));
+
+ /* Enable the selected ADC regular discontinuous mode */
+ hadc->Instance->CR1 |= (uint32_t)ADC_CR1_DISCEN;
+
+ /* Set the number of channels to be converted in discontinuous mode */
+ hadc->Instance->CR1 &= ~(ADC_CR1_DISCNUM);
+ hadc->Instance->CR1 |= ADC_CR1_DISCONTINUOUS(hadc->Init.NbrOfDiscConversion);
+ }
+ else
+ {
+ /* Disable the selected ADC regular discontinuous mode */
+ hadc->Instance->CR1 &= ~(ADC_CR1_DISCEN);
+ }
+
+ /* Set ADC number of conversion */
+ hadc->Instance->SQR1 &= ~(ADC_SQR1_L);
+ hadc->Instance->SQR1 |= ADC_SQR1(hadc->Init.NbrOfConversion);
+
+ /* Enable or disable ADC DMA continuous request */
+ hadc->Instance->CR2 &= ~(ADC_CR2_DDS);
+ hadc->Instance->CR2 |= ADC_CR2_DMAContReq(hadc->Init.DMAContinuousRequests);
+
+ /* Enable or disable ADC end of conversion selection */
+ hadc->Instance->CR2 &= ~(ADC_CR2_EOCS);
+ hadc->Instance->CR2 |= ADC_CR2_EOCSelection(hadc->Init.EOCSelection);
+}
+
+/**
+ * @brief DMA 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 ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
+{
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Check if an injected conversion is ready */
+ if(hadc->State == HAL_ADC_STATE_EOC_INJ)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_REG;
+ }
+
+ HAL_ADC_ConvCpltCallback(hadc);
+}
+
+/**
+ * @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 ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ /* Conversion complete callback */
+ HAL_ADC_ConvHalfCpltCallback(hadc);
+}
+
+/**
+ * @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 ADC_DMAError(DMA_HandleTypeDef *hdma)
+{
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ hadc->State= HAL_ADC_STATE_ERROR;
+ /* Set ADC error code to DMA error */
+ hadc->ErrorCode |= HAL_ADC_ERROR_DMA;
+ HAL_ADC_ErrorCallback(hadc);
+}
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_adc_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_adc_ex.c
new file mode 100644
index 0000000000..a5b4718cec
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_adc_ex.c
@@ -0,0 +1,854 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_adc_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the ADC extension peripheral:
+ * + Extended features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#)Initialize the ADC low level resources by implementing the HAL_ADC_MspInit():
+ (##) Enable the ADC interface clock using __HAL_RCC_ADC_CLK_ENABLE()
+ (##) 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()
+ (##) In case of using interrupts (e.g. HAL_ADC_Start_IT())
+ (+++) Configure the ADC interrupt priority using HAL_NVIC_SetPriority()
+ (+++) Enable the ADC IRQ handler using HAL_NVIC_EnableIRQ()
+ (+++) In ADC IRQ handler, call HAL_ADC_IRQHandler()
+ (##) In case of using DMA to control data transfer (e.g. HAL_ADC_Start_DMA())
+ (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE()
+ (+++) Configure and enable two DMA streams stream for managing data
+ transfer from peripheral to memory (output stream)
+ (+++) Associate the initialized DMA handle to the ADC DMA handle
+ using __HAL_LINKDMA()
+ (+++) Configure the priority and enable the NVIC for the transfer complete
+ interrupt on the two DMA Streams. The output stream should have higher
+ priority than the input stream.
+ (#) Configure the ADC Prescaler, conversion resolution and data alignment
+ using the HAL_ADC_Init() function.
+
+ (#) Configure the ADC Injected channels group features, use HAL_ADC_Init()
+ and HAL_ADC_ConfigChannel() functions.
+
+ (#) Three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Start the ADC peripheral using HAL_ADCEx_InjectedStart()
+ (+) Wait for end of conversion using HAL_ADC_PollForConversion(), at this stage
+ user can specify the value of timeout according to his end application
+ (+) To read the ADC converted values, use the HAL_ADCEx_InjectedGetValue() function.
+ (+) Stop the ADC peripheral using HAL_ADCEx_InjectedStop()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Start the ADC peripheral using HAL_ADCEx_InjectedStart_IT()
+ (+) Use HAL_ADC_IRQHandler() called under ADC_IRQHandler() Interrupt subroutine
+ (+) At ADC end of conversion HAL_ADCEx_InjectedConvCpltCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADCEx_InjectedConvCpltCallback
+ (+) In case of ADC Error, HAL_ADCEx_InjectedErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADCEx_InjectedErrorCallback
+ (+) Stop the ADC peripheral using HAL_ADCEx_InjectedStop_IT()
+
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Start the ADC peripheral using HAL_ADCEx_InjectedStart_DMA(), at this stage the user specify the length
+ of data to be transferred at each end of conversion
+ (+) At The end of data transfer ba HAL_ADCEx_InjectedConvCpltCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADCEx_InjectedConvCpltCallback
+ (+) In case of transfer Error, HAL_ADCEx_InjectedErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_ADCEx_InjectedErrorCallback
+ (+) Stop the ADC peripheral using HAL_ADCEx_InjectedStop_DMA()
+
+ *** Multi mode ADCs Regular channels configuration ***
+ ======================================================
+ [..]
+ (+) Select the Multi mode ADC regular channels features (dual or triple mode)
+ and configure the DMA mode using HAL_ADCEx_MultiModeConfigChannel() functions.
+ (+) Start the ADC peripheral using HAL_ADCEx_MultiModeStart_DMA(), at this stage the user specify the length
+ of data to be transferred at each end of conversion
+ (+) Read the ADCs converted values using the HAL_ADCEx_MultiModeGetValue() function.
+
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup ADCEx ADCEx
+ * @brief ADC Extended driver modules
+ * @{
+ */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup ADCEx_Private_Functions
+ * @{
+ */
+static void ADC_MultiModeDMAConvCplt(DMA_HandleTypeDef *hdma);
+static void ADC_MultiModeDMAError(DMA_HandleTypeDef *hdma);
+static void ADC_MultiModeDMAHalfConvCplt(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup ADCEx_Exported_Functions ADC Exported Functions
+ * @{
+ */
+
+/** @defgroup ADCEx_Exported_Functions_Group1 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Start conversion of injected channel.
+ (+) Stop conversion of injected channel.
+ (+) Start multimode and enable DMA transfer.
+ (+) Stop multimode and disable DMA transfer.
+ (+) Get result of injected channel conversion.
+ (+) Get result of multimode conversion.
+ (+) Configure injected channels.
+ (+) Configure multimode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the selected ADC software start conversion of the injected channels.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef* hadc)
+{
+ __IO uint32_t counter = 0;
+ uint32_t tmp1 = 0, tmp2 = 0;
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Check if a regular conversion is ongoing */
+ if(hadc->State == HAL_ADC_STATE_BUSY_REG)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_INJ;
+ }
+
+ /* Check if ADC peripheral is disabled in order to enable it and wait during
+ Tstab time the ADC's stabilization */
+ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+
+ /* Check if Multimode enabled */
+ if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI))
+ {
+ tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
+ tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
+ if(tmp1 && tmp2)
+ {
+ /* Enable the selected ADC software conversion for injected group */
+ hadc->Instance->CR2 |= ADC_CR2_JSWSTART;
+ }
+ }
+ else
+ {
+ tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
+ tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
+ if((hadc->Instance == ADC1) && tmp1 && tmp2)
+ {
+ /* Enable the selected ADC software conversion for injected group */
+ hadc->Instance->CR2 |= ADC_CR2_JSWSTART;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables the interrupt and starts ADC conversion of injected channels.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ *
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc)
+{
+ __IO uint32_t counter = 0;
+ uint32_t tmp1 = 0, tmp2 =0;
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Check if a regular conversion is ongoing */
+ if(hadc->State == HAL_ADC_STATE_BUSY_REG)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_INJ;
+ }
+
+ /* Set ADC error code to none */
+ hadc->ErrorCode = HAL_ADC_ERROR_NONE;
+
+ /* Check if ADC peripheral is disabled in order to enable it and wait during
+ Tstab time the ADC's stabilization */
+ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+
+ /* Enable the ADC end of conversion interrupt for injected group */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
+
+ /* Enable the ADC overrun interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Check if Multimode enabled */
+ if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI))
+ {
+ tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
+ tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
+ if(tmp1 && tmp2)
+ {
+ /* Enable the selected ADC software conversion for injected group */
+ hadc->Instance->CR2 |= ADC_CR2_JSWSTART;
+ }
+ }
+ else
+ {
+ tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
+ tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
+ if((hadc->Instance == ADC1) && tmp1 && tmp2)
+ {
+ /* Enable the selected ADC software conversion for injected group */
+ hadc->Instance->CR2 |= ADC_CR2_JSWSTART;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables ADC and stop conversion of injected channels.
+ *
+ * @note Caution: This function will stop also regular channels.
+ *
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef* hadc)
+{
+ /* Disable the Peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Poll for injected conversion complete
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param Timeout: Timeout value in millisecond.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check End of conversion flag */
+ while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC)))
+ {
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hadc->State= HAL_ADC_STATE_TIMEOUT;
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check if a regular conversion is ready */
+ if(hadc->State == HAL_ADC_STATE_EOC_REG)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ;
+ }
+
+ /* Return ADC state */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables the interrupt and stop ADC conversion of injected channels.
+ *
+ * @note Caution: This function will stop also regular channels.
+ *
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef* hadc)
+{
+ /* Disable the ADC end of conversion interrupt for regular group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
+
+ /* Disable the ADC end of conversion interrupt for injected group */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_CR1_JEOCIE);
+
+ /* Enable the Peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Gets the converted value from data register of injected channel.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param InjectedRank: the ADC injected rank.
+ * This parameter can be one of the following values:
+ * @arg ADC_INJECTED_RANK_1: Injected Channel1 selected
+ * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected
+ * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected
+ * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected
+ * @retval None
+ */
+uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank)
+{
+ __IO uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_INJECTED_RANK(InjectedRank));
+
+ /* Clear the ADCx's flag for injected end of conversion */
+ __HAL_ADC_CLEAR_FLAG(hadc,ADC_FLAG_JEOC);
+
+ /* Return the selected ADC converted value */
+ switch(InjectedRank)
+ {
+ case ADC_INJECTED_RANK_4:
+ {
+ tmp = hadc->Instance->JDR4;
+ }
+ break;
+ case ADC_INJECTED_RANK_3:
+ {
+ tmp = hadc->Instance->JDR3;
+ }
+ break;
+ case ADC_INJECTED_RANK_2:
+ {
+ tmp = hadc->Instance->JDR2;
+ }
+ break;
+ case ADC_INJECTED_RANK_1:
+ {
+ tmp = hadc->Instance->JDR1;
+ }
+ break;
+ default:
+ break;
+ }
+ return tmp;
+}
+
+/**
+ * @brief Enables ADC DMA request after last transfer (Multi-ADC mode) and enables ADC peripheral
+ *
+ * @note Caution: This function must be used only with the ADC master.
+ *
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param pData: Pointer to buffer in which transferred from ADC peripheral to memory will be stored.
+ * @param Length: The length of data to be transferred from ADC peripheral to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
+{
+ __IO uint32_t counter = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
+ assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
+ assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable ADC overrun interrupt */
+ __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
+
+ if (hadc->Init.DMAContinuousRequests != DISABLE)
+ {
+ /* Enable the selected ADC DMA request after last transfer */
+ ADC->CCR |= ADC_CCR_DDS;
+ }
+ else
+ {
+ /* Disable the selected ADC EOC rising on each regular channel conversion */
+ ADC->CCR &= ~ADC_CCR_DDS;
+ }
+
+ /* Set the DMA transfer complete callback */
+ hadc->DMA_Handle->XferCpltCallback = ADC_MultiModeDMAConvCplt;
+
+ /* Set the DMA half transfer complete callback */
+ hadc->DMA_Handle->XferHalfCpltCallback = ADC_MultiModeDMAHalfConvCplt;
+
+ /* Set the DMA error callback */
+ hadc->DMA_Handle->XferErrorCallback = ADC_MultiModeDMAError ;
+
+ /* Enable the DMA Stream */
+ HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&ADC->CDR, (uint32_t)pData, Length);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_BUSY_REG;
+
+ /* Check if ADC peripheral is disabled in order to enable it and wait during
+ Tstab time the ADC's stabilization */
+ if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
+ {
+ /* Enable the Peripheral */
+ __HAL_ADC_ENABLE(hadc);
+
+ /* Delay for temperature sensor stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
+ while(counter != 0)
+ {
+ counter--;
+ }
+ }
+
+ /* if no external trigger present enable software conversion of regular channels */
+ if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)
+ {
+ /* Enable the selected ADC software conversion for regular group */
+ hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables ADC DMA (multi-ADC mode) and disables ADC peripheral
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef* hadc)
+{
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Enable the Peripheral */
+ __HAL_ADC_DISABLE(hadc);
+
+ /* Disable ADC overrun interrupt */
+ __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR);
+
+ /* Disable the selected ADC DMA request after last transfer */
+ ADC->CCR &= ~ADC_CCR_DDS;
+
+ /* Disable the ADC DMA Stream */
+ HAL_DMA_Abort(hadc->DMA_Handle);
+
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Returns the last ADC1, ADC2 and ADC3 regular conversions results
+ * data in the selected multi mode.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval The converted data value.
+ */
+uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef* hadc)
+{
+ /* Return the multi mode conversion value */
+ return ADC->CDR;
+}
+
+/**
+ * @brief Injected conversion complete callback in non blocking mode
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @retval None
+ */
+__weak void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_ADC_InjectedConvCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Configures for the selected ADC injected channel its corresponding
+ * rank in the sequencer and its sample time.
+ * @param hadc: pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param sConfigInjected: ADC configuration structure for injected channel.
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef* hadc, ADC_InjectionConfTypeDef* sConfigInjected)
+{
+
+#ifdef USE_FULL_ASSERT
+ uint32_t tmp = 0;
+#endif /* USE_FULL_ASSERT */
+
+ /* Check the parameters */
+ assert_param(IS_ADC_CHANNEL(sConfigInjected->InjectedChannel));
+ assert_param(IS_ADC_INJECTED_RANK(sConfigInjected->InjectedRank));
+ assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime));
+ assert_param(IS_ADC_EXT_INJEC_TRIG(sConfigInjected->ExternalTrigInjecConv));
+ assert_param(IS_ADC_EXT_INJEC_TRIG_EDGE(sConfigInjected->ExternalTrigInjecConvEdge));
+ assert_param(IS_ADC_INJECTED_LENGTH(sConfigInjected->InjectedNbrOfConversion));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv));
+ assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjectedDiscontinuousConvMode));
+
+#ifdef USE_FULL_ASSERT
+ tmp = ADC_GET_RESOLUTION(hadc);
+ assert_param(IS_ADC_RANGE(tmp, sConfigInjected->InjectedOffset));
+#endif /* USE_FULL_ASSERT */
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* if ADC_Channel_10 ... ADC_Channel_18 is selected */
+ if (sConfigInjected->InjectedChannel > ADC_CHANNEL_9)
+ {
+ /* Clear the old sample time */
+ hadc->Instance->SMPR1 &= ~ADC_SMPR1(ADC_SMPR1_SMP10, sConfigInjected->InjectedChannel);
+
+ /* Set the new sample time */
+ hadc->Instance->SMPR1 |= ADC_SMPR1(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel);
+ }
+ else /* ADC_Channel include in ADC_Channel_[0..9] */
+ {
+ /* Clear the old sample time */
+ hadc->Instance->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, sConfigInjected->InjectedChannel);
+
+ /* Set the new sample time */
+ hadc->Instance->SMPR2 |= ADC_SMPR2(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel);
+ }
+
+ /*---------------------------- ADCx JSQR Configuration -----------------*/
+ hadc->Instance->JSQR &= ~(ADC_JSQR_JL);
+ hadc->Instance->JSQR |= ADC_SQR1(sConfigInjected->InjectedNbrOfConversion);
+
+ /* Rank configuration */
+
+ /* Clear the old SQx bits for the selected rank */
+ hadc->Instance->JSQR &= ~ADC_JSQR(ADC_JSQR_JSQ1, sConfigInjected->InjectedRank,sConfigInjected->InjectedNbrOfConversion);
+
+ /* Set the SQx bits for the selected rank */
+ hadc->Instance->JSQR |= ADC_JSQR(sConfigInjected->InjectedChannel, sConfigInjected->InjectedRank,sConfigInjected->InjectedNbrOfConversion);
+
+ /* Select external trigger to start conversion */
+ hadc->Instance->CR2 &= ~(ADC_CR2_JEXTSEL);
+ hadc->Instance->CR2 |= sConfigInjected->ExternalTrigInjecConv;
+
+ /* Select external trigger polarity */
+ hadc->Instance->CR2 &= ~(ADC_CR2_JEXTEN);
+ hadc->Instance->CR2 |= sConfigInjected->ExternalTrigInjecConvEdge;
+
+ if (sConfigInjected->AutoInjectedConv != DISABLE)
+ {
+ /* Enable the selected ADC automatic injected group conversion */
+ hadc->Instance->CR1 |= ADC_CR1_JAUTO;
+ }
+ else
+ {
+ /* Disable the selected ADC automatic injected group conversion */
+ hadc->Instance->CR1 &= ~(ADC_CR1_JAUTO);
+ }
+
+ if (sConfigInjected->InjectedDiscontinuousConvMode != DISABLE)
+ {
+ /* Enable the selected ADC injected discontinuous mode */
+ hadc->Instance->CR1 |= ADC_CR1_JDISCEN;
+ }
+ else
+ {
+ /* Disable the selected ADC injected discontinuous mode */
+ hadc->Instance->CR1 &= ~(ADC_CR1_JDISCEN);
+ }
+
+ switch(sConfigInjected->InjectedRank)
+ {
+ case 1:
+ /* Set injected channel 1 offset */
+ hadc->Instance->JOFR1 &= ~(ADC_JOFR1_JOFFSET1);
+ hadc->Instance->JOFR1 |= sConfigInjected->InjectedOffset;
+ break;
+ case 2:
+ /* Set injected channel 2 offset */
+ hadc->Instance->JOFR2 &= ~(ADC_JOFR2_JOFFSET2);
+ hadc->Instance->JOFR2 |= sConfigInjected->InjectedOffset;
+ break;
+ case 3:
+ /* Set injected channel 3 offset */
+ hadc->Instance->JOFR3 &= ~(ADC_JOFR3_JOFFSET3);
+ hadc->Instance->JOFR3 |= sConfigInjected->InjectedOffset;
+ break;
+ default:
+ /* Set injected channel 4 offset */
+ hadc->Instance->JOFR4 &= ~(ADC_JOFR4_JOFFSET4);
+ hadc->Instance->JOFR4 |= sConfigInjected->InjectedOffset;
+ break;
+ }
+
+ /* if ADC1 Channel_18 is selected enable VBAT Channel */
+ if ((hadc->Instance == ADC1) && (sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT))
+ {
+ /* Enable the VBAT channel*/
+ ADC->CCR |= ADC_CCR_VBATE;
+ }
+
+ /* if ADC1 Channel_16 or Channel_17 is selected enable TSVREFE Channel(Temperature sensor and VREFINT) */
+ if ((hadc->Instance == ADC1) && ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) || (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT)))
+ {
+ /* Enable the TSVREFE channel*/
+ ADC->CCR |= ADC_CCR_TSVREFE;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the ADC multi-mode
+ * @param hadc : pointer to a ADC_HandleTypeDef structure that contains
+ * the configuration information for the specified ADC.
+ * @param multimode : pointer to an ADC_MultiModeTypeDef structure that contains
+ * the configuration information for multimode.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_ADCEx_MultiModeConfigChannel(ADC_HandleTypeDef* hadc, ADC_MultiModeTypeDef* multimode)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_MODE(multimode->Mode));
+ assert_param(IS_ADC_DMA_ACCESS_MODE(multimode->DMAAccessMode));
+ assert_param(IS_ADC_SAMPLING_DELAY(multimode->TwoSamplingDelay));
+
+ /* Process locked */
+ __HAL_LOCK(hadc);
+
+ /* Set ADC mode */
+ ADC->CCR &= ~(ADC_CCR_MULTI);
+ ADC->CCR |= multimode->Mode;
+
+ /* Set the ADC DMA access mode */
+ ADC->CCR &= ~(ADC_CCR_DMA);
+ ADC->CCR |= multimode->DMAAccessMode;
+
+ /* Set delay between two sampling phases */
+ ADC->CCR &= ~(ADC_CCR_DELAY);
+ ADC->CCR |= multimode->TwoSamplingDelay;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hadc);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+ /**
+ * @brief DMA 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 ADC_MultiModeDMAConvCplt(DMA_HandleTypeDef *hdma)
+{
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Check if an injected conversion is ready */
+ if(hadc->State == HAL_ADC_STATE_EOC_INJ)
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_INJ_REG;
+ }
+ else
+ {
+ /* Change ADC state */
+ hadc->State = HAL_ADC_STATE_EOC_REG;
+ }
+
+ HAL_ADC_ConvCpltCallback(hadc);
+}
+
+/**
+ * @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 ADC_MultiModeDMAHalfConvCplt(DMA_HandleTypeDef *hdma)
+{
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ /* Conversion complete callback */
+ HAL_ADC_ConvHalfCpltCallback(hadc);
+}
+
+/**
+ * @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 ADC_MultiModeDMAError(DMA_HandleTypeDef *hdma)
+{
+ ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ hadc->State= HAL_ADC_STATE_ERROR;
+ /* Set ADC error code to DMA error */
+ hadc->ErrorCode |= HAL_ADC_ERROR_DMA;
+ HAL_ADC_ErrorCallback(hadc);
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_can.c b/stmhal/hal/f7/src/stm32f7xx_hal_can.c
new file mode 100644
index 0000000000..0f5d8a3135
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_can.c
@@ -0,0 +1,1435 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_can.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 and __HAL_RCC_CAN2_CLK_ENABLE() for CAN2
+ -@- In case you are using CAN2 only, you have to enable the CAN1 clock.
+
+ (#) 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 to AF9 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() function.
+
+ (#) Receive a CAN frame using HAL_CAN_Receive() 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup CAN CAN
+ * @brief CAN driver modules
+ * @{
+ */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup CAN_Private_Constants
+ * @{
+ */
+#define CAN_TIMEOUT_VALUE 10
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup 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 Initializes the CAN peripheral according to the specified
+ * parameters in the CAN_InitStruct.
+ * @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 InitStatus = 3;
+ 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)
+ {
+ InitStatus = CAN_INITSTATUS_FAILED;
+ }
+ else
+ {
+ /* 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)
+ {
+ InitStatus = CAN_INITSTATUS_FAILED;
+ }
+ else
+ {
+ InitStatus = CAN_INITSTATUS_SUCCESS;
+ }
+ }
+
+ if(InitStatus == 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 Configures 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;
+
+ /* 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;
+
+ /* Select the start slave bank */
+ CAN1->FMR &= ~((uint32_t)CAN_FMR_CAN2SB);
+ CAN1->FMR |= (uint32_t)(sFilterConfig->BankNumber << 8);
+
+ /* 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 Deinitializes the CANx 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 Initializes 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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CAN_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes 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)
+{
+ /* 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 IO operation functions
+ * @brief IO 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 Initiates and transmits a CAN frame message.
+ * @param hcan: pointer to a CAN_HandleTypeDef structure that contains
+ * the configuration information for the specified CAN.
+ * @param Timeout: Specify Timeout value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
+{
+ uint32_t transmitmailbox = 5;
+ 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;
+ }
+ else
+ {
+ transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
+ }
+
+ 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;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ }
+ 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 Initiates and transmits a CAN frame message.
+ * @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 = 5;
+ uint32_t tmp = 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));
+
+ tmp = hcan->State;
+ if((tmp == HAL_CAN_STATE_READY) || (tmp == 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;
+ }
+ else
+ {
+ transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
+ }
+
+ 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 Error warning Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG);
+
+ /* Enable Error passive Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV);
+
+ /* Enable Bus-off Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF);
+
+ /* Enable Last error code Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC);
+
+ /* Enable Error Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_ERR);
+
+ /* Enable Transmit mailbox empty Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_TME);
+
+ /* Request transmission */
+ hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
+ }
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Receives 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 value
+ * @param Timeout: Specify Timeout value
+ * @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;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ }
+ else
+ {
+ /* Change CAN state */
+ hcan->State = HAL_CAN_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hcan);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Receives 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
+ */
+HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
+{
+ uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_CAN_FIFO(FIFONumber));
+
+ tmp = hcan->State;
+ if((tmp == HAL_CAN_STATE_READY) || (tmp == 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 Error warning Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG);
+
+ /* Enable Error passive Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV);
+
+ /* Enable Bus-off Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF);
+
+ /* Enable Last error code Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC);
+
+ /* Enable Error Interrupt */
+ __HAL_CAN_ENABLE_IT(hcan, 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 Enters 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 Wakes 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 Handles 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)
+{
+ uint32_t tmp1 = 0, tmp2 = 0, tmp3 = 0;
+
+ /* Check End of transmission flag */
+ if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
+ {
+ tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0);
+ tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1);
+ tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2);
+ if(tmp1 || tmp2 || tmp3)
+ {
+ /* Call transmit function */
+ CAN_Transmit_IT(hcan);
+ }
+ }
+
+ tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0);
+ tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0);
+ /* Check End of reception flag for FIFO0 */
+ if((tmp1 != 0) && tmp2)
+ {
+ /* Call receive function */
+ CAN_Receive_IT(hcan, CAN_FIFO0);
+ }
+
+ tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1);
+ tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1);
+ /* Check End of reception flag for FIFO1 */
+ if((tmp1 != 0) && tmp2)
+ {
+ /* Call receive function */
+ CAN_Receive_IT(hcan, CAN_FIFO1);
+ }
+
+ tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG);
+ tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG);
+ tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
+ /* Check Error Warning Flag */
+ if(tmp1 && tmp2 && tmp3)
+ {
+ /* Set CAN error code to EWG error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
+ /* Clear Error Warning Flag */
+ __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_EWG);
+ }
+
+ tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV);
+ tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV);
+ tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
+ /* Check Error Passive Flag */
+ if(tmp1 && tmp2 && tmp3)
+ {
+ /* Set CAN error code to EPV error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
+ /* Clear Error Passive Flag */
+ __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_EPV);
+ }
+
+ tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF);
+ tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF);
+ tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
+ /* Check Bus-Off Flag */
+ if(tmp1 && tmp2 && tmp3)
+ {
+ /* Set CAN error code to BOF error */
+ hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
+ /* Clear Bus-Off Flag */
+ __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_BOF);
+ }
+
+ tmp1 = HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC);
+ tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC);
+ tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
+ /* Check Last error code Flag */
+ if((!tmp1) && tmp2 && tmp3)
+ {
+ tmp1 = (hcan->Instance->ESR) & CAN_ESR_LEC;
+ switch(tmp1)
+ {
+ 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)
+ {
+ /* 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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_CAN_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @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_RxCpltCallback(CAN_HandleTypeDef* 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)
+{
+ /* 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 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 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;
+}
+
+/**
+ * @}
+ */
+/**
+ * @brief Initiates and transmits 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 Error warning Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG);
+
+ /* Disable Error passive Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EPV);
+
+ /* Disable Bus-off Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_BOF);
+
+ /* Disable Last error code Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_LEC);
+
+ /* Disable Error Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, 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 Receives 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
+ * @retval None
+ */
+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 Error warning Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG);
+
+ /* Disable Error passive Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EPV);
+
+ /* Disable Bus-off Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_BOF);
+
+ /* Disable Last error code Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, CAN_IT_LEC);
+
+ /* Disable Error Interrupt */
+ __HAL_CAN_DISABLE_IT(hcan, 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/f7/src/stm32f7xx_hal_cortex.c b/stmhal/hal/f7/src/stm32f7xx_hal_cortex.c
new file mode 100644
index 0000000000..e8008351e1
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_cortex.c
@@ -0,0 +1,483 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_cortex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief CORTEX HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the CORTEX:
+ * + Initialization and de-initialization 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 according to the following table.
+ (#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority().
+ (#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ().
+ (#) please refer to programming manual for details in how to configure priority.
+
+ -@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ preemption 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 preemption 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 stm32f7xx_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
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup CORTEX CORTEX
+ * @brief CORTEX HAL module driver
+ * @{
+ */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup CORTEX_Exported_Functions CORTEX Exported Functions
+ * @{
+ */
+
+
+/** @defgroup CORTEX_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de-initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides the CORTEX HAL driver functions allowing to configure Interrupts
+ Systick functionalities
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Sets the priority grouping field (preemption 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 bits for preemption priority
+ * 4 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
+ * 3 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
+ * 2 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
+ * 1 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
+ * 0 bits for subpriority
+ * @note When the NVIC_PriorityGroup_0 is selected, IRQ preemption 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 Sets 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 (stm32f7xxxx.h))
+ * @param PreemptPriority: The preemption 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 Enables 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 (stm32f7xxxx.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 Disables 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 (stm32f7xxxx.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 Initiates a system reset request to reset the MCU.
+ * @retval None
+ */
+void HAL_NVIC_SystemReset(void)
+{
+ /* System Reset */
+ NVIC_SystemReset();
+}
+
+/**
+ * @brief Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ * 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);
+}
+/**
+ * @}
+ */
+
+/** @defgroup CORTEX_Exported_Functions_Group2 Peripheral Control functions
+ * @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
+ * @{
+ */
+
+#if (__MPU_PRESENT == 1)
+/**
+ * @brief Initializes and configures 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 */
+
+/**
+ * @brief Gets 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 Gets 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 (stm32f7xxxx.h))
+ * @param PriorityGroup: the priority grouping bits length.
+ * This parameter can be one of the following values:
+ * @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
+ * 4 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
+ * 3 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
+ * 2 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
+ * 1 bits for subpriority
+ * @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
+ * 0 bits 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 Sets 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 (stm32f7xxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Set interrupt pending */
+ NVIC_SetPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Gets Pending Interrupt (reads the pending register in the NVIC
+ * and returns 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 (stm32f7xxxx.h))
+ * @retval status: - 0 Interrupt status is not pending.
+ * - 1 Interrupt status is pending.
+ */
+uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Return 1 if pending else 0 */
+ return NVIC_GetPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Clears 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 (stm32f7xxxx.h))
+ * @retval None
+ */
+void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Clear pending interrupt */
+ NVIC_ClearPendingIRQ(IRQn);
+}
+
+/**
+ * @brief Gets active interrupt ( reads the active register in NVIC and returns 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 (stm32f7xxxx.h))
+ * @retval status: - 0 Interrupt status is not pending.
+ * - 1 Interrupt status is pending.
+ */
+uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
+{
+ /* Check the parameters */
+ assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
+
+ /* Return 1 if active else 0 */
+ return NVIC_GetActive(IRQn);
+}
+
+/**
+ * @brief Configures 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 This function handles 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
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_dac.c b/stmhal/hal/f7/src/stm32f7xx_hal_dac.c
new file mode 100644
index 0000000000..77adc61201
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_dac.c
@@ -0,0 +1,949 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_dac.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 ***
+ ====================
+ [..]
+ The device integrates two 12-bit Digital Analog Converters that can
+ be used independently or simultaneously (dual mode):
+ (#) DAC channel1 with DAC_OUT1 (PA4) as output
+ (#) DAC channel2 with DAC_OUT2 (PA5) as output
+
+ *** 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_Pin9) using DAC_TRIGGER_EXT_IT9.
+ The used pin (GPIOx_Pin9) must be configured in input mode.
+
+ (#) Timers TRGO: TIM2, TIM4, TIM5, TIM6, TIM7 and TIM8
+ (DAC_TRIGGER_T2_TRGO, DAC_TRIGGER_T4_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 wave generation feature ***
+ ===================================
+ [..]
+ Both DAC channels can be used to generate
+ (#) Noise wave using HAL_DACEx_NoiseWaveGenerate()
+ (#) Triangle wave using HAL_DACEx_TriangleWaveGenerate()
+
+ *** 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()
+ [..]
+ DMA1 requests are mapped as following:
+ (#) DAC channel1 : mapped on DMA1 Stream5 channel7 which must be
+ already configured
+ (#) DAC channel2 : mapped on DMA1 Stream6 channel7 which must be
+ already configured
+
+ -@- For Dual mode and specific signal (Triangle and noise) generation please
+ refer to Extension 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
+
+ *** 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 end of data transfer HAL_DAC_ConvCpltCallbackCh1()or HAL_DAC_ConvCpltCallbackCh2()
+ function is executed and user can add his own code by customization of function pointer
+ HAL_DAC_ConvCpltCallbackCh1 or HAL_DAC_ConvCpltCallbackCh2
+ (+) 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
+ (+) 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DAC DAC
+ * @brief DAC driver modules
+ * @{
+ */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup DAC_Private_Functions
+ * @{
+ */
+/* Private function prototypes -----------------------------------------------*/
+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 Initializes the DAC peripheral according to the specified parameters
+ * in the DAC_InitStruct.
+ * @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 Deinitializes 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 Initializes 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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DAC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes 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)
+{
+ /* 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)
+{
+ uint32_t tmp1 = 0, tmp2 = 0;
+
+ /* 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)
+ {
+ tmp1 = hdac->Instance->CR & DAC_CR_TEN1;
+ tmp2 = hdac->Instance->CR & DAC_CR_TSEL1;
+ /* Check if software trigger enabled */
+ if((tmp1 == DAC_CR_TEN1) && (tmp2 == DAC_CR_TSEL1))
+ {
+ /* Enable the selected DAC software conversion */
+ hdac->Instance->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1;
+ }
+ }
+ else
+ {
+ tmp1 = hdac->Instance->CR & DAC_CR_TEN2;
+ tmp2 = hdac->Instance->CR & DAC_CR_TSEL2;
+ /* Check if software trigger enabled */
+ if((tmp1 == DAC_CR_TEN2) && (tmp2 == DAC_CR_TSEL2))
+ {
+ /* Enable the selected DAC software conversion*/
+ hdac->Instance->SWTRIGR |= (uint32_t)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 */
+ 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 */
+ 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 Stream */
+ if(Channel == DAC_CHANNEL_1)
+ {
+ /* Enable the DAC DMA underrun interrupt */
+ __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
+
+ /* Enable the DMA Stream */
+ 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 Stream */
+ HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_DAC_ENABLE(hdac, Channel);
+
+ /* 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_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)
+ {
+ status = HAL_DMA_Abort(hdac->DMA_Handle1);
+ }
+ else /* Channel2 is used for */
+ {
+ status = HAL_DMA_Abort(hdac->DMA_Handle2);
+ }
+
+ /* 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;
+}
+
+/**
+ * @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 Handles DAC interrupt request
+ * @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)
+{
+ /* Check underrun channel 1 flag */
+ 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 channel1 DMA underrun error */
+ 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 */
+ hdac->Instance->CR &= ~DAC_CR_DMAEN1;
+
+ /* Error callback */
+ HAL_DAC_DMAUnderrunCallbackCh1(hdac);
+ }
+ /* Check underrun channel 2 flag */
+ 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 */
+ 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 */
+ hdac->Instance->CR &= ~DAC_CR_DMAEN2;
+
+ /* Error callback */
+ HAL_DACEx_DMAUnderrunCallbackCh2(hdac);
+ }
+}
+
+/**
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DAC_ConvCpltCallback 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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 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;
+
+ /* 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_CHANNEL(Channel));
+
+ /* Process locked */
+ __HAL_LOCK(hdac);
+
+ /* Change DAC state */
+ hdac->State = HAL_DAC_STATE_BUSY;
+
+ /* Get the DAC CR value */
+ tmpreg1 = hdac->Instance->CR;
+ /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */
+ tmpreg1 &= ~(((uint32_t)(DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1 | DAC_CR_BOFF1)) << Channel);
+ /* Configure for the selected DAC channel: buffer output, trigger */
+ /* Set TSELx and TENx bits according to DAC_Trigger value */
+ /* Set BOFFx bit according to DAC_OutputBuffer value */
+ tmpreg2 = (sConfig->DAC_Trigger | sConfig->DAC_OutputBuffer);
+ /* 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;
+}
+
+/**
+ * @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 channel1 selected data holding register */
+ *(__IO uint32_t *) tmp = Data;
+
+ /* 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 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 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;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @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/f7/src/stm32f7xx_hal_dac_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_dac_ex.c
new file mode 100644
index 0000000000..ca6d12b952
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_dac_ex.c
@@ -0,0 +1,376 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_dac_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief Extended DAC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of DAC extension peripheral:
+ * + Extended features functions
+ *
+ *
+ @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.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DACEx DACEx
+ * @brief DAC driver modules
+ * @{
+ */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup DACEx_Exported_Functions DAC Exported Functions
+ * @{
+ */
+
+/** @defgroup DACEx_Exported_Functions_Group1 Extended features functions
+ * @brief Extended features 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 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.
+ * @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;
+}
+
+/**
+ * @brief Enables or disables 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:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @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 selected 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 Enables or disables 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:
+ * @arg DAC_CHANNEL_1: DAC Channel1 selected
+ * @arg DAC_CHANNEL_2: DAC Channel2 selected
+ * @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 selected 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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DAC_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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
+ */
+}
+
+/**
+ * @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/f7/src/stm32f7xx_hal_dma.c b/stmhal/hal/f7/src/stm32f7xx_hal_dma.c
new file mode 100644
index 0000000000..1bb953aa30
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_dma.c
@@ -0,0 +1,921 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_dma.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 Stream
+ (except for internal SRAM/FLASH memories: no initialization is
+ necessary) please refer to Reference manual for connection between peripherals
+ and DMA requests .
+
+ (#) For a given Stream, program the required configuration through the following parameters:
+ Transfer Direction, Source and Destination data formats,
+ Circular, Normal or peripheral flow control mode, Stream Priority level,
+ Source and Destination Increment mode, FIFO mode and its Threshold (if needed),
+ Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function.
+
+ *** 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).
+ [..]
+ (#) 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.
+
+ -@- The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
+ possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
+ Half-Word data size for the peripheral to access its data register and set Word data size
+ for the Memory to gain in access time. Each two half words will be packed and written in
+ a single access to a Word in the Memory).
+
+ -@- When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
+ and Destination. In this case the Peripheral Data Size will be applied to both Source
+ and Destination.
+
+ *** DMA HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in DMA HAL driver.
+
+ (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream.
+ (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream.
+ (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level.
+ (+) __HAL_DMA_GET_FLAG: Get the DMA Stream pending flags.
+ (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Stream pending flags.
+ (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts.
+ (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts.
+ (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMA DMA
+ * @brief DMA HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup DMA_Private_Constants
+ * @{
+ */
+ #define HAL_TIMEOUT_DMA_ABORT ((uint32_t)1000) /* 1s */
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup DMA_Private_Functions
+ * @{
+ */
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
+/**
+ * @brief Sets the DMA Transfer parameter.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @param SrcAddress: The source memory Buffer address
+ * @param DstAddress: The destination memory Buffer address
+ * @param DataLength: The length of data to be transferred from source to destination
+ * @retval HAL status
+ */
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
+{
+ /* Clear DBM bit */
+ hdma->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM);
+
+ /* Configure DMA Stream data length */
+ hdma->Instance->NDTR = DataLength;
+
+ /* Peripheral to Memory */
+ if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
+ {
+ /* Configure DMA Stream destination address */
+ hdma->Instance->PAR = DstAddress;
+
+ /* Configure DMA Stream source address */
+ hdma->Instance->M0AR = SrcAddress;
+ }
+ /* Memory to Peripheral */
+ else
+ {
+ /* Configure DMA Stream source address */
+ hdma->Instance->PAR = SrcAddress;
+
+ /* Configure DMA Stream destination address */
+ hdma->Instance->M0AR = DstAddress;
+ }
+}
+
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @addtogroup DMA_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup DMA_Exported_Functions_Group1
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to initialize the DMA Stream source
+ and destination addresses, incrementation and data sizes, transfer direction,
+ circular/normal mode selection, memory-to-memory mode selection and Stream priority value.
+ [..]
+ The HAL_DMA_Init() function follows the DMA configuration procedures as described in
+ reference manual.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the DMA according to the specified
+ * parameters in the DMA_InitTypeDef and create the associated handle.
+ * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
+{
+ uint32_t tmp = 0;
+
+ /* Check the DMA peripheral state */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));
+ assert_param(IS_DMA_CHANNEL(hdma->Init.Channel));
+ assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
+ assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
+ assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
+ assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
+ assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
+ assert_param(IS_DMA_MODE(hdma->Init.Mode));
+ assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
+ assert_param(IS_DMA_FIFO_MODE_STATE(hdma->Init.FIFOMode));
+ /* Check the memory burst, peripheral burst and FIFO threshold parameters only
+ when FIFO mode is enabled */
+ if(hdma->Init.FIFOMode != DMA_FIFOMODE_DISABLE)
+ {
+ assert_param(IS_DMA_FIFO_THRESHOLD(hdma->Init.FIFOThreshold));
+ assert_param(IS_DMA_MEMORY_BURST(hdma->Init.MemBurst));
+ assert_param(IS_DMA_PERIPHERAL_BURST(hdma->Init.PeriphBurst));
+ }
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Get the CR register value */
+ tmp = hdma->Instance->CR;
+
+ /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
+ tmp &= ((uint32_t)~(DMA_SxCR_CHSEL | DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
+ DMA_SxCR_PL | DMA_SxCR_MSIZE | DMA_SxCR_PSIZE | \
+ DMA_SxCR_MINC | DMA_SxCR_PINC | DMA_SxCR_CIRC | \
+ DMA_SxCR_DIR | DMA_SxCR_CT | DMA_SxCR_DBM));
+
+ /* Prepare the DMA Stream configuration */
+ tmp |= hdma->Init.Channel | hdma->Init.Direction |
+ hdma->Init.PeriphInc | hdma->Init.MemInc |
+ hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
+ hdma->Init.Mode | hdma->Init.Priority;
+
+ /* the Memory burst and peripheral burst are not used when the FIFO is disabled */
+ if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
+ {
+ /* Get memory burst and peripheral burst */
+ tmp |= hdma->Init.MemBurst | hdma->Init.PeriphBurst;
+ }
+
+ /* Write to DMA Stream CR register */
+ hdma->Instance->CR = tmp;
+
+ /* Get the FCR register value */
+ tmp = hdma->Instance->FCR;
+
+ /* Clear Direct mode and FIFO threshold bits */
+ tmp &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
+
+ /* Prepare the DMA Stream FIFO configuration */
+ tmp |= hdma->Init.FIFOMode;
+
+ /* the FIFO threshold is not used when the FIFO mode is disabled */
+ if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
+ {
+ /* Get the FIFO threshold */
+ tmp |= hdma->Init.FIFOThreshold;
+ }
+
+ /* Write to DMA Stream FCR */
+ hdma->Instance->FCR = tmp;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the DMA peripheral
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
+{
+ /* Check the DMA peripheral state */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the DMA peripheral state */
+ if(hdma->State == HAL_DMA_STATE_BUSY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the selected DMA Streamx */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Reset DMA Streamx control register */
+ hdma->Instance->CR = 0;
+
+ /* Reset DMA Streamx number of data to transfer register */
+ hdma->Instance->NDTR = 0;
+
+ /* Reset DMA Streamx peripheral address register */
+ hdma->Instance->PAR = 0;
+
+ /* Reset DMA Streamx memory 0 address register */
+ hdma->Instance->M0AR = 0;
+
+ /* Reset DMA Streamx memory 1 address register */
+ hdma->Instance->M1AR = 0;
+
+ /* Reset DMA Streamx FIFO control register */
+ hdma->Instance->FCR = (uint32_t)0x00000021;
+
+ /* Clear all flags */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_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_FE_FLAG_INDEX(hdma));
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+
+ /* 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;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup DMA_Exported_Functions_Group2
+ *
+@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 Starts the DMA Transfer.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @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 Stream.
+ * @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 */
+ __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TC);
+
+ /* Enable the Half transfer complete interrupt */
+ __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
+
+ /* Enable the transfer Error interrupt */
+ __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TE);
+
+ /* Enable the FIFO Error interrupt */
+ __HAL_DMA_ENABLE_IT(hdma, DMA_IT_FE);
+
+ /* Enable the direct mode Error interrupt */
+ __HAL_DMA_ENABLE_IT(hdma, DMA_IT_DME);
+
+ /* Enable the Peripheral */
+ __HAL_DMA_ENABLE(hdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Aborts the DMA Transfer.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ *
+ * @note After disabling a DMA Stream, a check for wait until the DMA Stream is
+ * effectively disabled is added. If a Stream is disabled
+ * while a data transfer is ongoing, the current data will be transferred
+ * and the Stream 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 stream */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Check if the DMA Stream is effectively disabled */
+ while((hdma->Instance->CR & DMA_SxCR_EN) != 0)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_TIMEOUT;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Change the DMA state*/
+ hdma->State = HAL_DMA_STATE_READY;
+
+ 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 Stream.
+ * @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, tmp, tmp1, tmp2;
+ 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)
+ {
+ tmp = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
+ tmp1 = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
+ tmp2 = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
+ if((tmp != RESET) || (tmp1 != RESET) || (tmp2 != RESET))
+ {
+ if(tmp != RESET)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_TE;
+
+ /* Clear the transfer error flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
+ }
+ if(tmp1 != RESET)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_FE;
+
+ /* Clear the FIFO error flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
+ }
+ if(tmp2 != RESET)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_DME;
+
+ /* Clear the Direct Mode error flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
+ }
+ /* 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)
+ {
+ /* Multi_Buffering mode enabled */
+ if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
+ {
+ /* Clear the half transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+ /* Clear the transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
+
+ /* Current memory buffer used is Memory 0 */
+ if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_MEM0;
+ }
+ /* Current memory buffer used is Memory 1 */
+ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_MEM1;
+ }
+ }
+ else
+ {
+ /* Clear the half transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+ /* Clear the transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
+
+ /* The selected Streamx EN bit is cleared (DMA is disabled and all transfers
+ are complete) */
+ hdma->State = HAL_DMA_STATE_READY_MEM0;
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+ else
+ {
+ /* Multi_Buffering mode enabled */
+ if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
+ {
+ /* Clear the half transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+
+ /* Current memory buffer used is Memory 0 */
+ if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0;
+ }
+ /* Current memory buffer used is Memory 1 */
+ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_HALF_MEM1;
+ }
+ }
+ else
+ {
+ /* 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_MEM0;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles DMA interrupt request.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @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_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if(hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ }
+ /* FIFO Error Interrupt management ******************************************/
+ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)) != RESET)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != RESET)
+ {
+ /* Disable the FIFO Error interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_FE);
+
+ /* Clear the FIFO error flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_FE;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if(hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ }
+ /* Direct Mode Error Interrupt management ***********************************/
+ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)) != RESET)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != RESET)
+ {
+ /* Disable the direct mode Error interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_DME);
+
+ /* Clear the direct mode error flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_DME;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_ERROR;
+
+ /* 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)
+ {
+ /* Multi_Buffering mode enabled */
+ if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
+ {
+ /* Clear the half transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
+
+ /* Current memory buffer used is Memory 0 */
+ if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0;
+ }
+ /* Current memory buffer used is Memory 1 */
+ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_READY_HALF_MEM1;
+ }
+ }
+ else
+ {
+ /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
+ if((hdma->Instance->CR & DMA_SxCR_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_MEM0;
+ }
+
+ 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->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
+ {
+ /* Clear the transfer complete flag */
+ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
+
+ /* Current memory buffer used is Memory 1 */
+ if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
+ {
+ if(hdma->XferM1CpltCallback != NULL)
+ {
+ /* Transfer complete Callback for memory1 */
+ hdma->XferM1CpltCallback(hdma);
+ }
+ }
+ /* Current memory buffer used is Memory 0 */
+ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
+ {
+ if(hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete Callback for memory0 */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+ }
+ /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
+ else
+ {
+ if((hdma->Instance->CR & DMA_SxCR_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_MEM0;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if(hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete callback */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup DMA_Exported_Functions_Group3
+ *
+@verbatim
+ ===============================================================================
+ ##### State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the DMA state
+ (+) Get error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the DMA state.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL state
+ */
+HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
+{
+ 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 Stream.
+ * @retval DMA Error Code
+ */
+uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
+{
+ return hdma->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_flash.c b/stmhal/hal/f7/src/stm32f7xx_hal_flash.c
new file mode 100644
index 0000000000..b5ca6dcf46
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_flash.c
@@ -0,0 +1,817 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_flash.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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
+ (+) Prefetch on I-Code
+ (+) 64 cache lines of 128 bits on I-Code
+ (+) 8 cache lines of 128 bits on D-Code
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver provides functions and macros to configure and program the FLASH
+ memory of all STM32F7xx devices.
+
+ (#) FLASH Memory IO Programming functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Program functions: byte, half word, word and double word
+ (++) 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()
+ (++) Wait for last FLASH operation according to its status
+ (++) Get error flag status by calling HAL_SetErrorCode()
+ [..]
+ 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 interrupts
+ (+) Monitor the FLASH flags status
+ [..]
+ (@) For any Flash memory program operation (erase or program), the CPU clock frequency
+ (HCLK) must be at least 1MHz.
+ (@) The contents of the Flash memory are not guaranteed if a device reset occurs during
+ a Flash memory operation.
+ (@) Any attempt to read the Flash memory while it is being written or erased, causes the
+ bus to stall. Read operations are processed correctly once the program operation has
+ completed. This means that code or data fetches cannot be performed while a write/erase
+ operation is ongoing.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASH FLASH
+ * @brief FLASH HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup FLASH_Private_Constants
+ * @{
+ */
+#define SECTOR_MASK ((uint32_t)0xFFFFFF07)
+#define FLASH_TIMEOUT_VALUE ((uint32_t)50000)/* 50 s */
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup FLASH_Private_Variables
+ * @{
+ */
+/* Variable used for Erase sectors under interruption */
+FLASH_ProcessTypeDef pFlash;
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup FLASH_Private_Functions
+ * @{
+ */
+/* Program operations */
+static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
+static void FLASH_Program_Word(uint32_t Address, uint32_t Data);
+static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data);
+static void FLASH_Program_Byte(uint32_t Address, uint8_t Data);
+static void FLASH_SetErrorCode(void);
+
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
+/**
+ * @}
+ */
+
+/* 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 byte, halfword, word or double word 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
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+
+ /* 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)
+ {
+ switch(TypeProgram)
+ {
+ case FLASH_TYPEPROGRAM_BYTE :
+ {
+ /*Program byte (8-bit) at a specified address.*/
+ FLASH_Program_Byte(Address, (uint8_t) Data);
+ break;
+ }
+
+ case FLASH_TYPEPROGRAM_HALFWORD :
+ {
+ /*Program halfword (16-bit) at a specified address.*/
+ FLASH_Program_HalfWord(Address, (uint16_t) Data);
+ break;
+ }
+
+ case FLASH_TYPEPROGRAM_WORD :
+ {
+ /*Program word (32-bit) at a specified address.*/
+ FLASH_Program_Word(Address, (uint32_t) Data);
+ break;
+ }
+
+ case FLASH_TYPEPROGRAM_DOUBLEWORD :
+ {
+ /*Program double word (64-bit) at a specified address.*/
+ FLASH_Program_DoubleWord(Address, Data);
+ break;
+ }
+ default :
+ break;
+ }
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the program operation is completed, disable the PG Bit */
+ FLASH->CR &= (~FLASH_CR_PG);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Program byte, halfword, word or double word 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
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+
+ /* Enable End of FLASH Operation interrupt */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP);
+
+ /* Enable Error source interrupt */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_ERR);
+
+ /* Clear pending flags (if any) */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |\
+ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR| FLASH_FLAG_ERSERR);
+
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM;
+ pFlash.Address = Address;
+
+ switch(TypeProgram)
+ {
+ case FLASH_TYPEPROGRAM_BYTE :
+ {
+ /*Program byte (8-bit) at a specified address.*/
+ FLASH_Program_Byte(Address, (uint8_t) Data);
+ break;
+ }
+
+ case FLASH_TYPEPROGRAM_HALFWORD :
+ {
+ /*Program halfword (16-bit) at a specified address.*/
+ FLASH_Program_HalfWord(Address, (uint16_t) Data);
+ break;
+ }
+
+ case FLASH_TYPEPROGRAM_WORD :
+ {
+ /*Program word (32-bit) at a specified address.*/
+ FLASH_Program_Word(Address, (uint32_t) Data);
+ break;
+ }
+
+ case FLASH_TYPEPROGRAM_DOUBLEWORD :
+ {
+ /*Program double word (64-bit) at a specified address.*/
+ FLASH_Program_DoubleWord(Address, Data);
+ break;
+ }
+ default :
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief This function handles FLASH interrupt request.
+ * @retval None
+ */
+void HAL_FLASH_IRQHandler(void)
+{
+ uint32_t temp = 0;
+
+ /* If the program operation is completed, disable the PG Bit */
+ FLASH->CR &= (~FLASH_CR_PG);
+
+ /* If the erase operation is completed, disable the SER Bit */
+ FLASH->CR &= (~FLASH_CR_SER);
+ FLASH->CR &= SECTOR_MASK;
+
+ /* if the erase operation is completed, disable the MER Bit */
+ FLASH->CR &= (~FLASH_MER_BIT);
+
+ /* Check FLASH End of Operation flag */
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != RESET)
+ {
+ switch (pFlash.ProcedureOnGoing)
+ {
+ case FLASH_PROC_SECTERASE :
+ {
+ /* Nb of sector to erased can be decreased */
+ pFlash.NbSectorsToErase--;
+
+ /* Check if there are still sectors to erase */
+ if(pFlash.NbSectorsToErase != 0)
+ {
+ temp = pFlash.Sector;
+ /* Indicate user which sector has been erased */
+ HAL_FLASH_EndOfOperationCallback(temp);
+
+ /* Clear pending flags (if any) */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+
+ /* Increment sector number */
+ temp = ++pFlash.Sector;
+ FLASH_Erase_Sector(temp, pFlash.VoltageForErase);
+ }
+ else
+ {
+ /* No more sectors to Erase, user callback can be called.*/
+ /* Reset Sector and stop Erase sectors procedure */
+ pFlash.Sector = temp = 0xFFFFFFFF;
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(temp);
+ /* Sector Erase procedure is completed */
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ }
+ break;
+ }
+
+ case FLASH_PROC_MASSERASE :
+ {
+ /* MassErase ended. Return the selected bank : in this product we don't have Banks */
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(0);
+ /* MAss Erase procedure is completed */
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ break;
+ }
+
+ case FLASH_PROC_PROGRAM :
+ {
+ /*Program ended. Return the selected address*/
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ /* Programming procedure is completed */
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
+ break;
+ }
+ default :
+ break;
+ }
+ }
+
+ /* Check FLASH operation error flags */
+ if(__HAL_FLASH_GET_FLAG((FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR )) != RESET)
+ {
+ switch (pFlash.ProcedureOnGoing)
+ {
+ case FLASH_PROC_SECTERASE :
+ {
+ /* return the faulty sector */
+ temp = pFlash.Sector;
+ pFlash.Sector = 0xFFFFFFFF;
+ break;
+ }
+ case FLASH_PROC_MASSERASE :
+ {
+ /* No return in case of Mass Erase */
+ temp = 0;
+ break;
+ }
+ case FLASH_PROC_PROGRAM :
+ {
+ /*return the faulty address*/
+ temp = pFlash.Address;
+ break;
+ }
+ default :
+ break;
+ }
+ /*Save the Error code*/
+ FLASH_SetErrorCode();
+
+ /* FLASH error interrupt user callback */
+ HAL_FLASH_OperationErrorCallback(temp);
+ /* Clear FLASH error pending bits */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR );
+
+ /*Stop the procedure ongoing */
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ }
+
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
+ {
+ /* Disable End of FLASH Operation interrupt */
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP);
+
+ /* Disable Error source interrupt */
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_ERR);
+
+ /* 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
+ * - Sectors Erase: Sector which has been erased (if 0xFFFFFFFF, it means that
+ * all the selected sectors have been erased)
+ * - Program : Address which was selected for data program
+ * - Mass Erase : No return value expected
+ * @retval None
+ */
+__weak void HAL_FLASH_EndOfOperationCallback(uint32_t 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
+ * - Sectors Erase: Sector which has been erased (if 0xFFFFFFFF, it means that
+ * all the selected sectors have been erased)
+ * - Program : Address which was selected for data program
+ * - Mass Erase : No return value expected
+ * @retval None
+ */
+__weak void HAL_FLASH_OperationErrorCallback(uint32_t 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((FLASH->CR & FLASH_CR_LOCK) != RESET)
+ {
+ /* Authorize the FLASH Registers access */
+ FLASH->KEYR = FLASH_KEY1;
+ FLASH->KEYR = FLASH_KEY2;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Locks the FLASH control register access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Lock(void)
+{
+ /* Set the LOCK Bit to lock the FLASH Registers access */
+ FLASH->CR |= FLASH_CR_LOCK;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Unlock the FLASH Option Control Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
+{
+ if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET)
+ {
+ /* Authorizes the Option Byte register programming */
+ FLASH->OPTKEYR = FLASH_OPT_KEY1;
+ FLASH->OPTKEYR = FLASH_OPT_KEY2;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Lock the FLASH Option Control Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
+{
+ /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
+ FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Launch the option byte loading.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
+{
+ /* Set the OPTSTRT bit in OPTCR register */
+ FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
+
+ /* 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 FLASH_ERROR_ERS: FLASH Erasing Sequence error flag
+ * @arg FLASH_ERROR_PGP: FLASH Programming Parallelism error flag
+ * @arg FLASH_ERROR_PGA: FLASH Programming Alignment error flag
+ * @arg FLASH_ERROR_WRP: FLASH Write protected error flag
+ * @arg FLASH_ERROR_OPERATION: FLASH operation Error flag
+ */
+uint32_t HAL_FLASH_GetError(void)
+{
+ return pFlash.ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Wait for a FLASH operation to complete.
+ * @param Timeout: maximum flash operationtimeout
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Clear Error Code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* 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 */
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ if(__HAL_FLASH_GET_FLAG((FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \
+ FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR )) != RESET)
+ {
+ /*Save the error code*/
+ FLASH_SetErrorCode();
+ return HAL_ERROR;
+ }
+
+ /* If there is an error flag set */
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Program a double word (64-bit) at a specified address.
+ * @note This function must be used when the device voltage range is from
+ * 2.7V to 3.6V and an External Vpp is present.
+ *
+ * @note If an erase and a program operations are requested simultaneously,
+ * the erase operation is performed before the program one.
+ *
+ * @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_ADDRESS(Address));
+
+ /* If the previous operation is completed, proceed to program the new data */
+ FLASH->CR &= CR_PSIZE_MASK;
+ FLASH->CR |= FLASH_PSIZE_DOUBLE_WORD;
+ FLASH->CR |= FLASH_CR_PG;
+
+ *(__IO uint64_t*)Address = Data;
+
+ /* Data synchronous Barrier (DSB) Just after the write operation
+ This will force the CPU to respect the sequence of instruction (no optimization).*/
+ __DSB();
+}
+
+
+/**
+ * @brief Program word (32-bit) at a specified address.
+ * @note This function must be used when the device voltage range is from
+ * 2.7V to 3.6V.
+ *
+ * @note If an erase and a program operations are requested simultaneously,
+ * the erase operation is performed before the program one.
+ *
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed.
+ * @retval None
+ */
+static void FLASH_Program_Word(uint32_t Address, uint32_t Data)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_ADDRESS(Address));
+
+ /* If the previous operation is completed, proceed to program the new data */
+ FLASH->CR &= CR_PSIZE_MASK;
+ FLASH->CR |= FLASH_PSIZE_WORD;
+ FLASH->CR |= FLASH_CR_PG;
+
+ *(__IO uint32_t*)Address = Data;
+
+ /* Data synchronous Barrier (DSB) Just after the write operation
+ This will force the CPU to respect the sequence of instruction (no optimization).*/
+ __DSB();
+}
+
+/**
+ * @brief Program a half-word (16-bit) at a specified address.
+ * @note This function must be used when the device voltage range is from
+ * 2.7V to 3.6V.
+ *
+ * @note If an erase and a program operations are requested simultaneously,
+ * the erase operation is performed before the program one.
+ *
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed.
+ * @retval None
+ */
+static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_ADDRESS(Address));
+
+ /* If the previous operation is completed, proceed to program the new data */
+ FLASH->CR &= CR_PSIZE_MASK;
+ FLASH->CR |= FLASH_PSIZE_HALF_WORD;
+ FLASH->CR |= FLASH_CR_PG;
+
+ *(__IO uint16_t*)Address = Data;
+
+ /* Data synchronous Barrier (DSB) Just after the write operation
+ This will force the CPU to respect the sequence of instruction (no optimization).*/
+ __DSB();
+
+}
+
+/**
+ * @brief Program byte (8-bit) at a specified address.
+ * @note This function must be used when the device voltage range is from
+ * 2.7V to 3.6V.
+ *
+ * @note If an erase and a program operations are requested simultaneously,
+ * the erase operation is performed before the program one.
+ *
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed.
+ * @retval None
+ */
+static void FLASH_Program_Byte(uint32_t Address, uint8_t Data)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_ADDRESS(Address));
+
+ /* If the previous operation is completed, proceed to program the new data */
+ FLASH->CR &= CR_PSIZE_MASK;
+ FLASH->CR |= FLASH_PSIZE_BYTE;
+ FLASH->CR |= FLASH_CR_PG;
+
+ *(__IO uint8_t*)Address = Data;
+
+ /* Data synchronous Barrier (DSB) Just after the write operation
+ This will force the CPU to respect the sequence of instruction (no optimization).*/
+ __DSB();
+}
+
+/**
+ * @brief Set the specific FLASH error flag.
+ * @retval None
+ */
+static void FLASH_SetErrorCode(void)
+{
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) != RESET)
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR) != RESET)
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGPERR) != RESET)
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_PGP;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_ERSERR) != RESET)
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_ERS;
+ }
+
+ if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR) != RESET)
+ {
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_OPERATION;
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_flash_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_flash_ex.c
new file mode 100644
index 0000000000..359f09eedd
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_flash_ex.c
@@ -0,0 +1,817 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_flash_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief Extended FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the FLASH extension peripheral:
+ * + Extended programming operations functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### Flash Extension features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the FLASH interface for STM32F727xx/437xx and
+ 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 STM32F7xx 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 sector, 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 functions: Use HAL_FLASHEx_OBProgram() to :
+ (++) Set/Reset the write protection
+ (++) Set the Read protection Level
+ (++) Set the BOR level
+ (++) Program the user Option Bytes
+ (#) Advanced Option Bytes Programming functions: Use HAL_FLASHEx_AdvOBProgram() to :
+ (++) Extended space (bank 2) erase function
+ (++) Full FLASH space (2 Mo) erase (bank 1 and bank 2)
+ (++) Dual Boot activation
+ (++) Write protection configuration for bank 2
+ (++) PCROP protection configuration and control for both banks
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASHEx FLASHEx
+ * @brief FLASH HAL Extension module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup FLASHEx_Private_Constants
+ * @{
+ */
+#define SECTOR_MASK ((uint32_t)0xFFFFFF07)
+#define FLASH_TIMEOUT_VALUE ((uint32_t)50000)/* 50 s */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup FLASHEx_Private_Variables
+ * @{
+ */
+extern FLASH_ProcessTypeDef pFlash;
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup FLASHEx_Private_Functions
+ * @{
+ */
+/* Option bytes control */
+static void FLASH_MassErase(uint8_t VoltageRange);
+static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector);
+static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector);
+static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint32_t Level);
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t Wwdg, uint32_t Iwdg, uint32_t Stop, uint32_t Stdby, uint32_t Iwdgstop, uint32_t Iwdgstdby);
+static HAL_StatusTypeDef FLASH_OB_BOR_LevelConfig(uint8_t Level);
+static HAL_StatusTypeDef FLASH_OB_BootAddressConfig(uint32_t BootOption, uint32_t Address);
+static uint32_t FLASH_OB_GetUser(void);
+static uint32_t FLASH_OB_GetWRP(void);
+static uint8_t FLASH_OB_GetRDP(void);
+static uint32_t FLASH_OB_GetBOR(void);
+static uint32_t FLASH_OB_GetBootAddress(uint32_t BootOption);
+
+extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup FLASHEx_Exported_Functions FLASHEx 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 Extension FLASH
+ programming operations Operations.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory sectors
+ * @param[in] pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that
+ * contains the configuration information for the erasing.
+ *
+ * @param[out] SectorError: pointer to variable that
+ * contains the configuration information on faulty sector in case of error
+ * (0xFFFFFFFF means that all the sectors have been correctly erased)
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
+{
+ HAL_StatusTypeDef status = HAL_ERROR;
+ uint32_t 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)
+ {
+ /*Initialization of SectorError variable*/
+ *SectorError = 0xFFFFFFFF;
+
+ if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /*Mass erase to be done*/
+ FLASH_MassErase((uint8_t) pEraseInit->VoltageRange);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* if the erase operation is completed, disable the MER Bit */
+ FLASH->CR &= (~FLASH_MER_BIT);
+ }
+ else
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector));
+
+ /* Erase by sector by sector to be done*/
+ for(index = pEraseInit->Sector; index < (pEraseInit->NbSectors + pEraseInit->Sector); index++)
+ {
+ FLASH_Erase_Sector(index, (uint8_t) pEraseInit->VoltageRange);
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ /* If the erase operation is completed, disable the SER Bit */
+ FLASH->CR &= (~FLASH_CR_SER);
+ FLASH->CR &= SECTOR_MASK;
+
+ if(status != HAL_OK)
+ {
+ /* In case of error, stop erase procedure and return the faulty sector*/
+ *SectorError = index;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Perform a mass erase or erase the specified FLASH memory sectors 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));
+
+ /* Enable End of FLASH Operation interrupt */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP);
+
+ /* Enable Error source interrupt */
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_ERR);
+
+ /* Clear pending flags (if any) */
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |\
+ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR| FLASH_FLAG_ERSERR);
+
+ if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /*Mass erase to be done*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE;
+ FLASH_MassErase((uint8_t) pEraseInit->VoltageRange);
+ }
+ else
+ {
+ /* Erase by sector to be done*/
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector));
+
+ pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE;
+ pFlash.NbSectorsToErase = pEraseInit->NbSectors;
+ pFlash.Sector = pEraseInit->Sector;
+ pFlash.VoltageForErase = (uint8_t)pEraseInit->VoltageRange;
+
+ /*Erase 1st sector and wait for IT*/
+ FLASH_Erase_Sector(pEraseInit->Sector, pEraseInit->VoltageRange);
+ }
+
+ 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));
+
+ /* Write protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP)
+ {
+ assert_param(IS_WRPSTATE(pOBInit->WRPState));
+ if(pOBInit->WRPState == OB_WRPSTATE_ENABLE)
+ {
+ /*Enable of Write protection on the selected Sector*/
+ status = FLASH_OB_EnableWRP(pOBInit->WRPSector);
+ }
+ else
+ {
+ /*Disable of Write protection on the selected Sector*/
+ status = FLASH_OB_DisableWRP(pOBInit->WRPSector);
+ }
+ }
+
+ /* Read protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_RDP) == OPTIONBYTE_RDP)
+ {
+ status = FLASH_OB_RDP_LevelConfig(pOBInit->RDPLevel);
+ }
+
+ /* USER configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_USER) == OPTIONBYTE_USER)
+ {
+ status = FLASH_OB_UserConfig(pOBInit->USERConfig & OB_WWDG_SW,
+ pOBInit->USERConfig & OB_IWDG_SW,
+ pOBInit->USERConfig & OB_STOP_NO_RST,
+ pOBInit->USERConfig & OB_STDBY_NO_RST,
+ pOBInit->USERConfig & OB_IWDG_STOP_ACTIVE,
+ pOBInit->USERConfig & OB_IWDG_STDBY_ACTIVE);
+ }
+
+ /* BOR Level configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_BOR) == OPTIONBYTE_BOR)
+ {
+ status = FLASH_OB_BOR_LevelConfig(pOBInit->BORLevel);
+ }
+
+ /* Boot 0 Address configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_BOOTADDR_0) == OPTIONBYTE_BOOTADDR_0)
+ {
+ status = FLASH_OB_BootAddressConfig(OPTIONBYTE_BOOTADDR_0, pOBInit->BootAddr0);
+ }
+
+ /* Boot 1 Address configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_BOOTADDR_1) == OPTIONBYTE_BOOTADDR_1)
+ {
+ status = FLASH_OB_BootAddressConfig(OPTIONBYTE_BOOTADDR_1, pOBInit->BootAddr1);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Get the Option byte configuration
+ * @param pOBInit: pointer to an FLASH_OBInitStruct structure that
+ * contains the configuration information for the programming.
+ *
+ * @retval None
+ */
+void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ pOBInit->OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER |\
+ OPTIONBYTE_BOR | OPTIONBYTE_BOOTADDR_0 | OPTIONBYTE_BOOTADDR_1;
+
+ /*Get WRP*/
+ pOBInit->WRPSector = FLASH_OB_GetWRP();
+
+ /*Get RDP Level*/
+ pOBInit->RDPLevel = FLASH_OB_GetRDP();
+
+ /*Get USER*/
+ pOBInit->USERConfig = FLASH_OB_GetUser();
+
+ /*Get BOR Level*/
+ pOBInit->BORLevel = FLASH_OB_GetBOR();
+
+ /*Get Boot Address when Boot pin = 0 */
+ pOBInit->BootAddr0 = FLASH_OB_GetBootAddress(OPTIONBYTE_BOOTADDR_0);
+
+ /*Get Boot Address when Boot pin = 1 */
+ pOBInit->BootAddr1 = FLASH_OB_GetBootAddress(OPTIONBYTE_BOOTADDR_1);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Full erase of FLASH memory sectors
+ * @param VoltageRange: The device voltage range which defines the erase parallelism.
+ * This parameter can be one of the following values:
+ * @arg VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V,
+ * the operation will be done by byte (8-bit)
+ * @arg VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V,
+ * the operation will be done by half word (16-bit)
+ * @arg VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V,
+ * the operation will be done by word (32-bit)
+ * @arg VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp,
+ * the operation will be done by double word (64-bit)
+ *
+ * @retval HAL Status
+ */
+static void FLASH_MassErase(uint8_t VoltageRange)
+{
+ uint32_t tmp_psize = 0;
+
+ /* Check the parameters */
+ assert_param(IS_VOLTAGERANGE(VoltageRange));
+
+ /* if the previous operation is completed, proceed to erase all sectors */
+ FLASH->CR &= CR_PSIZE_MASK;
+ FLASH->CR |= tmp_psize;
+ FLASH->CR |= FLASH_CR_MER;
+ FLASH->CR |= FLASH_CR_STRT;
+ /* Data synchronous Barrier (DSB) Just after the write operation
+ This will force the CPU to respect the sequence of instruction (no optimization).*/
+ __DSB();
+}
+
+/**
+ * @brief Erase the specified FLASH memory sector
+ * @param Sector: FLASH sector to erase
+ * The value of this parameter depend on device used within the same series
+ * @param VoltageRange: The device voltage range which defines the erase parallelism.
+ * This parameter can be one of the following values:
+ * @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V,
+ * the operation will be done by byte (8-bit)
+ * @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V,
+ * the operation will be done by half word (16-bit)
+ * @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V,
+ * the operation will be done by word (32-bit)
+ * @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp,
+ * the operation will be done by double word (64-bit)
+ *
+ * @retval None
+ */
+void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
+{
+ uint32_t tmp_psize = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_SECTOR(Sector));
+ assert_param(IS_VOLTAGERANGE(VoltageRange));
+
+ if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
+ {
+ tmp_psize = FLASH_PSIZE_BYTE;
+ }
+ else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
+ {
+ tmp_psize = FLASH_PSIZE_HALF_WORD;
+ }
+ else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
+ {
+ tmp_psize = FLASH_PSIZE_WORD;
+ }
+ else
+ {
+ tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
+ }
+
+ /* If the previous operation is completed, proceed to erase the sector */
+ FLASH->CR &= CR_PSIZE_MASK;
+ FLASH->CR |= tmp_psize;
+ FLASH->CR &= SECTOR_MASK;
+ FLASH->CR |= FLASH_CR_SER | (Sector << POSITION_VAL(FLASH_CR_SNB));
+ FLASH->CR |= FLASH_CR_STRT;
+
+ /* Data synchronous Barrier (DSB) Just after the write operation
+ This will force the CPU to respect the sequence of instruction (no optimization).*/
+ __DSB();
+}
+
+/**
+ * @brief Enable the write protection of the desired bank1 or bank 2 sectors
+ *
+ * @note When the memory read protection level is selected (RDP level = 1),
+ * it is not possible to program or erase the flash sector i if CortexM4
+ * debug features are connected or boot code is executed in RAM, even if nWRPi = 1
+ * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1).
+ *
+ * @param WRPSector: specifies the sector(s) to be write protected.
+ * This parameter can be one of the following values:
+ * @arg WRPSector: A value between OB_WRP_SECTOR_0 and OB_WRP_SECTOR_7
+ * @arg OB_WRP_SECTOR_All
+ *
+ * @retval HAL FLASH State
+ */
+static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_WRP_SECTOR(WRPSector));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /*Write protection enabled on sectors */
+ FLASH->OPTCR &= (~WRPSector);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Disable the write protection of the desired bank1 or bank 2 sectors
+ *
+ * @note When the memory read protection level is selected (RDP level = 1),
+ * it is not possible to program or erase the flash sector i if CortexM4
+ * debug features are connected or boot code is executed in RAM, even if nWRPi = 1
+ *
+ * @param WRPSector: specifies the sector(s) to be write protected.
+ * This parameter can be one of the following values:
+ * @arg WRPSector: A value between OB_WRP_SECTOR_0 and OB_WRP_SECTOR_7
+ * @arg OB_WRP_Sector_All
+ *
+ *
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_WRP_SECTOR(WRPSector));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ /* Write protection disabled on sectors */
+ FLASH->OPTCR |= (WRPSector);
+ }
+
+ return status;
+}
+
+
+
+
+/**
+ * @brief Set the read protection level.
+ * @param Level: 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
+ *
+ * @note WARNING: When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0
+ *
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint32_t Level)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_RDP_LEVEL(Level));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ MODIFY_REG(FLASH->OPTCR, FLASH_OPTCR_RDP, Level);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Program the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY.
+ * @param Wwdg: Selects the IWDG mode
+ * This parameter can be one of the following values:
+ * @arg OB_WWDG_SW: Software WWDG selected
+ * @arg OB_WWDG_HW: Hardware WWDG selected
+ * @param Iwdg: Selects the WWDG mode
+ * This parameter can be one of the following values:
+ * @arg OB_IWDG_SW: Software IWDG selected
+ * @arg OB_IWDG_HW: Hardware IWDG selected
+ * @param Stop: Reset event when entering STOP mode.
+ * This parameter can be one of the following values:
+ * @arg OB_STOP_NO_RST: No reset generated when entering in STOP
+ * @arg OB_STOP_RST: Reset generated when entering in STOP
+ * @param Stdby: Reset event when entering Standby mode.
+ * This parameter can be one of the following values:
+ * @arg OB_STDBY_NO_RST: No reset generated when entering in STANDBY
+ * @arg OB_STDBY_RST: Reset generated when entering in STANDBY
+ * @param Iwdgstop: Independent watchdog counter freeze in Stop mode.
+ * This parameter can be one of the following values:
+ * @arg OB_IWDG_STOP_FREEZE: Freeze IWDG counter in STOP
+ * @arg OB_IWDG_STOP_ACTIVE: IWDG counter active in STOP
+ * @param Iwdgstdby: Independent watchdog counter freeze in standby mode.
+ * This parameter can be one of the following values:
+ * @arg OB_IWDG_STDBY_FREEZE: Freeze IWDG counter in STANDBY
+ * @arg OB_IWDG_STDBY_ACTIVE: IWDG counter active in STANDBY
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t Wwdg, uint32_t Iwdg, uint32_t Stop, uint32_t Stdby, uint32_t Iwdgstop, uint32_t Iwdgstdby )
+{
+ uint32_t useroptionmask = 0x00;
+ uint32_t useroptionvalue = 0x00;
+
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_WWDG_SOURCE(Wwdg));
+ assert_param(IS_OB_IWDG_SOURCE(Iwdg));
+ assert_param(IS_OB_STOP_SOURCE(Stop));
+ assert_param(IS_OB_STDBY_SOURCE(Stdby));
+ assert_param(IS_OB_IWDG_STOP_FREEZE(Iwdgstop));
+ assert_param(IS_OB_IWDG_STDBY_FREEZE(Iwdgstdby));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ useroptionmask = (FLASH_OPTCR_WWDG_SW | FLASH_OPTCR_IWDG_SW | FLASH_OPTCR_nRST_STOP | \
+ FLASH_OPTCR_nRST_STDBY | FLASH_OPTCR_IWDG_STOP | FLASH_OPTCR_IWDG_STDBY);
+
+ useroptionvalue = (Iwdg | Wwdg | Stop | Stdby | Iwdgstop | Iwdgstdby);
+
+ /* Update User Option Byte */
+ MODIFY_REG(FLASH->OPTCR, useroptionmask, useroptionvalue);
+ }
+
+ return status;
+
+}
+
+/**
+ * @brief Set the BOR Level.
+ * @param Level: specifies the Option Bytes BOR Reset Level.
+ * This parameter can be one of the following values:
+ * @arg OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V
+ * @arg OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V
+ * @arg OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V
+ * @arg OB_BOR_OFF: Supply voltage ranges from 1.62 to 2.1 V
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_BOR_LevelConfig(uint8_t Level)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_BOR_LEVEL(Level));
+
+ /* Set the BOR Level */
+ MODIFY_REG(FLASH->OPTCR, FLASH_OPTCR_BOR_LEV, Level);
+
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Configure Boot base address.
+ *
+ * @param BootOption : specifies Boot base address depending from Boot pin = 0 or pin = 1
+ * This parameter can be one of the following values:
+ * @arg OPTIONBYTE_BOOTADDR_0 : Boot address based when Boot pin = 0
+ * @arg OPTIONBYTE_BOOTADDR_1 : Boot address based when Boot pin = 1
+ * @param Address: specifies Boot base address
+ * This parameter can be one of the following values:
+ * @arg OB_BOOTADDR_ITCM_RAM : Boot from ITCM RAM (0x00000000)
+ * @arg OB_BOOTADDR_SYSTEM : Boot from System memory bootloader (0x00100000)
+ * @arg OB_BOOTADDR_ITCM_FLASH : Boot from Flash on ITCM interface (0x00200000)
+ * @arg OB_BOOTADDR_AXIM_FLASH : Boot from Flash on AXIM interface (0x08000000)
+ * @arg OB_BOOTADDR_DTCM_RAM : Boot from DTCM RAM (0x20000000)
+ * @arg OB_BOOTADDR_SRAM1 : Boot from SRAM1 (0x20010000)
+ * @arg OB_BOOTADDR_SRAM2 : Boot from SRAM2 (0x2004C000)
+ *
+ * @retval HAL Status
+ */
+static HAL_StatusTypeDef FLASH_OB_BootAddressConfig(uint32_t BootOption, uint32_t Address)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_OB_BOOT_ADDRESS(Address));
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if(status == HAL_OK)
+ {
+ if(BootOption == OPTIONBYTE_BOOTADDR_0)
+ {
+ MODIFY_REG(FLASH->OPTCR1, FLASH_OPTCR1_BOOT_ADD0, Address);
+ }
+ else
+ {
+ MODIFY_REG(FLASH->OPTCR1, FLASH_OPTCR1_BOOT_ADD1, (Address << 16));
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Return the FLASH User Option Byte value.
+ * @retval uint32_t FLASH User Option Bytes values: IWDG_SW(Bit0), RST_STOP(Bit1)
+ * and RST_STDBY(Bit2).
+ */
+static uint32_t FLASH_OB_GetUser(void)
+{
+ /* Return the User Option Byte */
+ return ((uint32_t)(FLASH->OPTCR & 0xC00000F0));
+}
+
+/**
+ * @brief Return the FLASH Write Protection Option Bytes value.
+ * @retval uint32_t FLASH Write Protection Option Bytes value
+ */
+static uint32_t FLASH_OB_GetWRP(void)
+{
+ /* Return the FLASH write protection Register value */
+ return ((uint32_t)(FLASH->OPTCR & 0x00FF0000));
+}
+
+/**
+ * @brief Returns the FLASH Read Protection level.
+ * @retval FlagStatus FLASH ReadOut Protection Status:
+ * 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
+ */
+static uint8_t FLASH_OB_GetRDP(void)
+{
+ uint8_t readstatus = OB_RDP_LEVEL_0;
+
+ if (((FLASH->OPTCR & FLASH_OPTCR_RDP) >> 8) == OB_RDP_LEVEL_0)
+ {
+ readstatus = OB_RDP_LEVEL_0;
+ }
+ else if (((FLASH->OPTCR & FLASH_OPTCR_RDP) >> 8) == OB_RDP_LEVEL_2)
+ {
+ readstatus = OB_RDP_LEVEL_2;
+ }
+ else
+ {
+ readstatus = OB_RDP_LEVEL_1;
+ }
+
+ return readstatus;
+}
+
+/**
+ * @brief Returns the FLASH BOR level.
+ * @retval uint32_t The FLASH BOR level:
+ * - OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V
+ * - OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V
+ * - OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V
+ * - OB_BOR_OFF : Supply voltage ranges from 1.62 to 2.1 V
+ */
+static uint32_t FLASH_OB_GetBOR(void)
+{
+ /* Return the FLASH BOR level */
+ return ((uint32_t)(FLASH->OPTCR & 0x0C));
+}
+
+/**
+ * @brief Configure Boot base address.
+ *
+ * @param BootOption : specifies Boot base address depending from Boot pin = 0 or pin = 1
+ * This parameter can be one of the following values:
+ * @arg OPTIONBYTE_BOOTADDR_0 : Boot address based when Boot pin = 0
+ * @arg OPTIONBYTE_BOOTADDR_1 : Boot address based when Boot pin = 1
+ *
+ * @retval uint32_t Boot Base Address:
+ * - OB_BOOTADDR_ITCM_RAM : Boot from ITCM RAM (0x00000000)
+ * - OB_BOOTADDR_SYSTEM : Boot from System memory bootloader (0x00100000)
+ * - OB_BOOTADDR_ITCM_FLASH : Boot from Flash on ITCM interface (0x00200000)
+ * - OB_BOOTADDR_AXIM_FLASH : Boot from Flash on AXIM interface (0x08000000)
+ * - OB_BOOTADDR_DTCM_RAM : Boot from DTCM RAM (0x20000000)
+ * - OB_BOOTADDR_SRAM1 : Boot from SRAM1 (0x20010000)
+ * - OB_BOOTADDR_SRAM2 : Boot from SRAM2 (0x2004C000)
+ */
+static uint32_t FLASH_OB_GetBootAddress(uint32_t BootOption)
+{
+ uint32_t Address = 0;
+
+ /* Return the Boot base Address */
+ if(BootOption == OPTIONBYTE_BOOTADDR_0)
+ {
+ Address = FLASH->OPTCR1 & FLASH_OPTCR1_BOOT_ADD0;
+ }
+ else
+ {
+ Address = ((FLASH->OPTCR1 & FLASH_OPTCR1_BOOT_ADD1) >> 16);
+ }
+
+ return Address;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_gpio.c b/stmhal/hal/f7/src/stm32f7xx_hal_gpio.c
new file mode 100644
index 0000000000..daec5d6258
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_gpio.c
@@ -0,0 +1,540 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_gpio.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 #####
+ ==============================================================================
+ [..]
+ Subject to the specific hardware characteristics of each I/O port listed in the datasheet, each
+ port bit of the General Purpose IO (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.
+
+ [..]
+ 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 23 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup GPIO GPIO
+ * @brief GPIO HAL module driver
+ * @{
+ */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup GPIO_Private_Constants GPIO Private Constants
+ * @{
+ */
+#define GPIO_MODE ((uint32_t)0x00000003)
+#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 macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup GPIO_Exported_Functions GPIO Exported Functions
+ * @{
+ */
+
+/** @defgroup GPIO_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 de-initialize the GPIOs
+ to be ready for use.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
+ * @param GPIOx: where x can be (A..K) to select the GPIO peripheral.
+ * @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 ioposition = 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 */
+ for(position = 0; position < GPIO_NUMBER; position++)
+ {
+ /* Get the IO position */
+ ioposition = ((uint32_t)0x01) << position;
+ /* Get the current IO position */
+ iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
+
+ if(iocurrent == ioposition)
+ {
+ /*--------------------- 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 parameter */
+ 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_MODER0 << (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_OSPEEDER_OSPEEDR0 << (position * 2));
+ temp |= (GPIO_Init->Speed << (position * 2));
+ GPIOx->OSPEEDR = temp;
+
+ /* Configure the IO Output Type */
+ temp = GPIOx->OTYPER;
+ temp &= ~(GPIO_OTYPER_OT_0 << position) ;
+ temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);
+ GPIOx->OTYPER = temp;
+ }
+
+ /* Activate the Pull-up or Pull down resistor for the current IO */
+ temp = GPIOx->PUPDR;
+ temp &= ~(GPIO_PUPDR_PUPDR0 << (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 |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03)));
+ SYSCFG->EXTICR[position >> 2] = temp;
+
+ /* Clear EXTI line configuration */
+ temp = EXTI->IMR;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->IMR = temp;
+
+ temp = EXTI->EMR;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->EMR = temp;
+
+ /* Clear Rising Falling edge configuration */
+ temp = EXTI->RTSR;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->RTSR = temp;
+
+ temp = EXTI->FTSR;
+ temp &= ~((uint32_t)iocurrent);
+ if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->FTSR = temp;
+ }
+ }
+ }
+}
+
+/**
+ * @brief De-initializes the GPIOx peripheral registers to their default reset values.
+ * @param GPIOx: where x can be (A..K) to select the GPIO peripheral.
+ * @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;
+ uint32_t ioposition = 0x00;
+ uint32_t iocurrent = 0x00;
+ uint32_t tmp = 0x00;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
+
+ /* Configure the port pins */
+ for(position = 0; position < GPIO_NUMBER; position++)
+ {
+ /* Get the IO position */
+ ioposition = ((uint32_t)0x01) << position;
+ /* Get the current IO position */
+ iocurrent = (GPIO_Pin) & ioposition;
+
+ if(iocurrent == ioposition)
+ {
+ /*------------------------- GPIO Mode Configuration --------------------*/
+ /* Configure IO Direction in Input Floating Mode */
+ GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (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_OSPEEDER_OSPEEDR0 << (position * 2));
+
+ /* Configure the default value IO Output Type */
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT_0 << position) ;
+
+ /* Deactivate the Pull-up and Pull-down resistor for the current IO */
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));
+
+ /*------------------------- EXTI Mode Configuration --------------------*/
+ tmp = SYSCFG->EXTICR[position >> 2];
+ tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
+ if(tmp == ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03))))
+ {
+ /* Configure the External Interrupt or event for the current IO */
+ tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
+ SYSCFG->EXTICR[position >> 2] &= ~tmp;
+
+ /* Clear EXTI line configuration */
+ EXTI->IMR &= ~((uint32_t)iocurrent);
+ EXTI->EMR &= ~((uint32_t)iocurrent);
+
+ /* Clear Rising Falling edge configuration */
+ EXTI->RTSR &= ~((uint32_t)iocurrent);
+ EXTI->FTSR &= ~((uint32_t)iocurrent);
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
+ * @brief GPIO Read and Write
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Reads the specified input port pin.
+ * @param GPIOx: where x can be (A..K) to select the GPIO peripheral.
+ * @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 Sets or clears the selected data port bit.
+ *
+ * @note This function uses GPIOx_BSRR register 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..K) to select the GPIO peripheral.
+ * @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 = GPIO_Pin;
+ }
+ else
+ {
+ GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
+ }
+}
+
+/**
+ * @brief Toggles the specified GPIO pins.
+ * @param GPIOx: Where x can be (A..I) to select the GPIO peripheral.
+ * @param GPIO_Pin: Specifies the pins 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 Locks 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..F) to select the GPIO peripheral for STM32F7 family
+ * @param GPIO_Pin: specifies the port bit 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_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 This function handles EXTI interrupt request.
+ * @param GPIO_Pin: Specifies the pins connected 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 callbacks.
+ * @param GPIO_Pin: Specifies the pins connected EXTI line
+ * @retval None
+ */
+__weak void HAL_GPIO_EXTI_Callback(uint16_t 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/f7/src/stm32f7xx_hal_i2c.c b/stmhal/hal/f7/src/stm32f7xx_hal_i2c.c
new file mode 100644
index 0000000000..2c51ee21da
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_i2c.c
@@ -0,0 +1,4110 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_i2c.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 implement 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 stream
+ (+++) Enable the DMAx interface clock using
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx Stream
+ (+++) 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 Stream
+
+ (#) 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 customed 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
+
+ *** Interrupt mode IO MEM operation ***
+ =======================================
+ [..]
+ (+) Write an amount of data in no-blocking mode with Interrupt to a specific memory address using
+ HAL_I2C_Mem_Write_IT()
+ (+) At MEM 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 no-blocking mode with Interrupt from a specific memory address using
+ HAL_I2C_Mem_Read_IT()
+ (+) At MEM 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 no-blocking mode with DMA to a specific memory address using
+ HAL_I2C_Mem_Write_DMA()
+ (+) At MEM 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 no-blocking mode with DMA from a specific memory address using
+ HAL_I2C_Mem_Read_DMA()
+ (+) At MEM 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 : Checks 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2C I2C
+ * @brief I2C HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup I2C_Private_Constants I2C Private Constants
+ * @{
+ */
+#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 */
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup 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);
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout);
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout);
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout);
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout);
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout);
+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout);
+
+static HAL_StatusTypeDef I2C_MasterTransmit_ISR(I2C_HandleTypeDef *hi2c);
+static HAL_StatusTypeDef I2C_MasterReceive_ISR(I2C_HandleTypeDef *hi2c);
+
+static HAL_StatusTypeDef I2C_SlaveTransmit_ISR(I2C_HandleTypeDef *hi2c);
+static HAL_StatusTypeDef I2C_SlaveReceive_ISR(I2C_HandleTypeDef *hi2c);
+
+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
+ de-initialize 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 create 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;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes 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;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief I2C MSP Init.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C MSP DeInit
+ * @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)
+{
+ /* 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 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);
+
+ hi2c->State = HAL_I2C_STATE_MASTER_BUSY_TX;
+ 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) != 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 TXE flag is set */
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout) != 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) != 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;
+
+ /* 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 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);
+
+ hi2c->State = HAL_I2C_STATE_MASTER_BUSY_RX;
+ 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_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK)
+ {
+ 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) != 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, I2C_TIMEOUT_STOPF) != 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;
+
+ /* 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)
+{
+ 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_SLAVE_BUSY_RX;
+ 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) != 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) != 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) != 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) != 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;
+ }
+ }
+
+ /* Read data from TXDR */
+ hi2c->Instance->TXDR = (*pData++);
+ Size--;
+ }while(Size > 0);
+
+ /* Wait until STOP flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != 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) != 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;
+
+ /* 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)
+{
+ 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_SLAVE_BUSY_RX;
+ 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) != 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) != 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) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ 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, I2C_TIMEOUT_STOPF) != 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) != 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;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in no-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_MASTER_BUSY_TX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ 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 */
+ __HAL_I2C_ENABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_TXI );
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in no-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_MASTER_BUSY_RX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ 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 */
+ __HAL_I2C_ENABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI );
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in no-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_SLAVE_BUSY_TX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* 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 */
+ __HAL_I2C_ENABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_TXI );
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in no-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_SLAVE_BUSY_RX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* 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 */
+ __HAL_I2C_ENABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in no-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)
+{
+ 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_MASTER_BUSY_TX;
+ 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) != 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;
+ }
+ }
+
+
+ /* 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 no-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)
+{
+ 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_MASTER_BUSY_RX;
+ 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_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, I2C_TIMEOUT_RXNE) != 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 Transmit in slave mode an amount of data in no-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)
+{
+ 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_SLAVE_BUSY_TX;
+ 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) != 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) != 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) != 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 no-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)
+{
+ 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_SLAVE_BUSY_RX;
+ 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) != 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) != 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 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);
+
+ hi2c->State = HAL_I2C_STATE_MEM_BUSY_TX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout) != 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) != 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) != 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, I2C_TIMEOUT_STOPF) != 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;
+
+ /* 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 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);
+
+ hi2c->State = HAL_I2C_STATE_MEM_BUSY_RX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Send Slave Address and Memory Address */
+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout) != 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) != 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) != 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, I2C_TIMEOUT_STOPF) != 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;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in no-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)
+{
+ /* 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);
+
+ hi2c->State = HAL_I2C_STATE_MEM_BUSY_TX;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ 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) != 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 */
+ __HAL_I2C_ENABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_TXI );
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in no-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)
+{
+ /* 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);
+
+ hi2c->State = HAL_I2C_STATE_MEM_BUSY_RX;
+
+ 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) != 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 */
+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_RXI );
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in no-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)
+{
+ /* 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);
+
+ hi2c->State = HAL_I2C_STATE_MEM_BUSY_TX;
+ 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) != 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) != 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 no-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)
+{
+ /* 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);
+
+ hi2c->State = HAL_I2C_STATE_MEM_BUSY_RX;
+
+ 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) != 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) != 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) != 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) != 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) != 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;
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup 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)
+{
+ /* I2C in mode Transmitter ---------------------------------------------------*/
+ if (((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TC) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET)) && (__HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI | I2C_IT_ADDRI)) == SET))
+ {
+ /* Slave mode selected */
+ if (hi2c->State == HAL_I2C_STATE_SLAVE_BUSY_TX)
+ {
+ I2C_SlaveTransmit_ISR(hi2c);
+ }
+ }
+
+ if (((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TC) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)) && (__HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI)) == SET))
+ {
+ /* Master mode selected */
+ if ((hi2c->State == HAL_I2C_STATE_MASTER_BUSY_TX) || (hi2c->State == HAL_I2C_STATE_MEM_BUSY_TX))
+ {
+ I2C_MasterTransmit_ISR(hi2c);
+ }
+ }
+
+ /* I2C in mode Receiver ----------------------------------------------------*/
+ if (((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TC) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET)) && (__HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_RXI | I2C_IT_ADDRI)) == SET))
+ {
+ /* Slave mode selected */
+ if (hi2c->State == HAL_I2C_STATE_SLAVE_BUSY_RX)
+ {
+ I2C_SlaveReceive_ISR(hi2c);
+ }
+ }
+ if (((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TC) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) || (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)) && (__HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_RXI)) == SET))
+ {
+ /* Master mode selected */
+ if ((hi2c->State == HAL_I2C_STATE_MASTER_BUSY_RX) || (hi2c->State == HAL_I2C_STATE_MEM_BUSY_RX))
+ {
+ I2C_MasterReceive_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_NONE)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+}
+
+/**
+ * @brief Master Tx Transfer completed callbacks.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Master Rx Transfer completed callbacks.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/** @brief Slave Tx Transfer completed callbacks.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Rx Transfer completed callbacks.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Tx Transfer completed callbacks.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Rx Transfer completed callbacks.
+ * @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)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2C_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C error callbacks.
+ * @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)
+{
+ /* 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 and Errors functions
+ * @brief Peripheral State and Errors functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection permit to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the I2C 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 hi2c->State;
+}
+
+/**
+ * @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 Handle Interrupt Flags Master Transmit 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_MasterTransmit_ISR(I2C_HandleTypeDef *hi2c)
+{
+ uint16_t DevAddress;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == SET)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++);
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) == SET)
+ {
+ 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
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferCount, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ hi2c->XferSize = hi2c->XferCount;
+ }
+ }
+ else
+ {
+ /* 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)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ else
+ {
+ /* 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_STOPF) == SET)
+ {
+ /* Disable ERR, TC, STOP, NACK, TXI interrupt */
+ __HAL_I2C_DISABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_TXI );
+
+ /* 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;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ if(hi2c->State == HAL_I2C_STATE_MEM_BUSY_TX)
+ {
+ HAL_I2C_MemTxCpltCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle Interrupt Flags Master Receive 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_MasterReceive_ISR(I2C_HandleTypeDef *hi2c)
+{
+ uint16_t DevAddress;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TCR) == SET)
+ {
+ 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
+ {
+ I2C_TransferConfig(hi2c,DevAddress,hi2c->XferCount, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ hi2c->XferSize = hi2c->XferCount;
+ }
+ }
+ else
+ {
+ /* 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)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ else
+ {
+ /* 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_STOPF) == SET)
+ {
+ /* Disable ERR, TC, STOP, NACK, TXI interrupt */
+ __HAL_I2C_DISABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_RXI );
+
+ /* 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;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ if(hi2c->State == HAL_I2C_STATE_MEM_BUSY_RX)
+ {
+ HAL_I2C_MemRxCpltCallback(hi2c);
+ }
+ else
+ {
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+ }
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Handle Interrupt Flags Slave Transmit 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_SlaveTransmit_ISR(I2C_HandleTypeDef *hi2c)
+{
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) != RESET)
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal usecase, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if(hi2c->XferCount == 0)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+ else
+ {
+ /* if no, error usecase, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* 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_ADDR) == SET)
+ {
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+ /* Check first if STOPF is set */
+ /* to prevent a Write Data in TX buffer */
+ /* which is stuck in TXDR until next */
+ /* communication with Master */
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ /* Disable ERRI, TCI, STOPI, NACKI, ADDRI, RXI, TXI interrupt */
+ __HAL_I2C_DISABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI );
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == SET)
+ {
+ /* Write data to TXDR only if XferCount not reach "0" */
+ /* A TXIS flag can be set, during STOP treatment */
+ if(hi2c->XferCount > 0)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++);
+ hi2c->XferCount--;
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Handle Interrupt Flags Slave Receive 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_SlaveReceive_ISR(I2C_HandleTypeDef *hi2c)
+{
+ /* 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ HAL_I2C_ErrorCallback(hi2c);
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET)
+ {
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ /* Disable ERRI, TCI, STOPI, NACKI, ADDRI, RXI, TXI interrupt */
+ __HAL_I2C_DISABLE_IT(hi2c,I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_RXI );
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ HAL_I2C_SlaveRxCpltCallback(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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout)
+{
+ I2C_TransferConfig(hi2c,DevAddress,MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != 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) != 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) != 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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout)
+{
+ I2C_TransferConfig(hi2c,DevAddress,MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != 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) != 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) != 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)
+{
+ uint16_t DevAddress;
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* 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) != 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) != 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;
+ 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) != 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) != 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;
+ 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) != 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;
+
+ /* 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)
+{
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Wait until STOP flag is set */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != 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) != 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;
+
+ /* 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)
+{
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+ uint16_t DevAddress;
+
+ /* 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) != 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) != 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;
+ 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) != 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) != 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;
+
+ 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) != 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;
+
+ /* 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)
+{
+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ /* Wait until STOPF flag is reset */
+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != 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) != 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;
+
+ /* 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)
+{
+ uint16_t DevAddress;
+ I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* 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) != 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) != 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;
+ 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) != 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) != 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;
+ 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) != 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;
+
+ /* 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)
+{
+ I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+ uint16_t DevAddress;
+
+ /* 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) != 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) != 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;
+ 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) != 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) != 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;
+ 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) != 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;
+
+ /* 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->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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* 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;
+ /* 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;
+ /* 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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if(I2C_IsAcknowledgeFailed(hi2c, Timeout) != 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;
+
+ /* 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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout)
+{
+ uint32_t tickstart = 0x00;
+ tickstart = HAL_GetTick();
+
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if(I2C_IsAcknowledgeFailed(hi2c, Timeout) != 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;
+
+ /* 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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout)
+{
+ uint32_t tickstart = 0x00;
+ tickstart = HAL_GetTick();
+
+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
+ {
+ /* 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;
+
+ /* 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
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout)
+{
+ uint32_t tickstart = 0x00;
+ tickstart = HAL_GetTick();
+
+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Generate stop if necessary only in case of I2C peripheral in MASTER mode */
+ if((hi2c->State == HAL_I2C_STATE_MASTER_BUSY_TX) || (hi2c->State == HAL_I2C_STATE_MEM_BUSY_TX)
+ || (hi2c->State == HAL_I2C_STATE_MEM_BUSY_RX))
+ {
+ /* No need to generate the STOP condition if AUTOEND mode is enabled */
+ /* Generate the STOP condition only in case of SOFTEND mode is enabled */
+ if((hi2c->Instance->CR2 & I2C_AUTOEND_MODE) != I2C_AUTOEND_MODE)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ }
+
+ /* 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;
+ /* 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);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_AF;
+ hi2c->State= HAL_I2C_STATE_READY;
+
+ /* 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 I2C_RELOAD_MODE: Enable Reload mode .
+ * @arg I2C_AUTOEND_MODE: Enable Automatic end mode.
+ * @arg 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 I2C_NO_STARTSTOP: Don't Generate stop and start condition.
+ * @arg I2C_GENERATE_STOP: Generate stop condition (Size should be set to 0).
+ * @arg I2C_GENERATE_START_READ: Generate Restart for read request.
+ * @arg 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;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_i2s.c b/stmhal/hal/f7/src/stm32f7xx_hal_i2s.c
new file mode 100644
index 0000000000..f0fd09a07e
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_i2s.c
@@ -0,0 +1,1535 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_i2s.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief I2S HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Integrated Interchip Sound (I2S) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ The I2S HAL driver can be used as follows:
+
+ (#) Declare a I2S_HandleTypeDef handle structure.
+ (#) Initialize the I2S low level resources by implement the HAL_I2S_MspInit() API:
+ (##) Enable the SPIx interface clock.
+ (##) I2S pins configuration:
+ (+++) Enable the clock for the I2S GPIOs.
+ (+++) Configure these I2S pins as alternate function pull-up.
+ (##) NVIC configuration if you need to use interrupt process (HAL_I2S_Transmit_IT()
+ and HAL_I2S_Receive_IT() APIs).
+ (+++) Configure the I2Sx interrupt priority.
+ (+++) Enable the NVIC I2S IRQ handle.
+ (##) DMA Configuration if you need to use DMA process (HAL_I2S_Transmit_DMA()
+ and HAL_I2S_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 I2S DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
+ DMA Tx/Rx Channel.
+
+ (#) Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity
+ using HAL_I2S_Init() function.
+
+ -@- The specific I2S interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_I2S_ENABLE_IT() and __HAL_I2S_DISABLE_IT() inside the transmit and receive process.
+ -@- Make sure that either:
+ (+@) I2S clock is configured based on SYSCLK or
+ (+@) External clock source is configured after setting correctly
+ the define constant EXTERNAL_CLOCK_VALUE in the stm32f3xx_hal_conf.h file.
+
+ (#) Three mode of operations are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_I2S_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_I2S_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non blocking mode using HAL_I2S_Transmit_IT()
+ (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
+ (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxCpltCallback
+ (+) Receive an amount of data in non blocking mode using HAL_I2S_Receive_IT()
+ (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxCpltCallback
+ (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2S_ErrorCallback
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Send an amount of data in non blocking mode (DMA) using HAL_I2S_Transmit_DMA()
+ (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
+ (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_TxCpltCallback
+ (+) Receive an amount of data in non blocking mode (DMA) using HAL_I2S_Receive_DMA()
+ (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_I2S_RxCpltCallback
+ (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_I2S_ErrorCallback
+ (+) Pause the DMA Transfer using HAL_I2S_DMAPause()
+ (+) Resume the DMA Transfer using HAL_I2S_DMAResume()
+ (+) Stop the DMA Transfer using HAL_I2S_DMAStop()
+
+ *** I2S HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in I2S HAL driver.
+
+ (+) __HAL_I2S_ENABLE: Enable the specified SPI peripheral (in I2S mode)
+ (+) __HAL_I2S_DISABLE: Disable the specified SPI peripheral (in I2S mode)
+ (+) __HAL_I2S_ENABLE_IT : Enable the specified I2S interrupts
+ (+) __HAL_I2S_DISABLE_IT : Disable the specified I2S interrupts
+ (+) __HAL_I2S_GET_FLAG: Check whether the specified I2S flag is set or not
+
+ [..]
+ (@) You can refer to the I2S HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2S I2S
+ * @brief I2S HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup I2S_Private_Functions I2S Private Functions
+ * @{
+ */
+static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void I2S_DMAError(DMA_HandleTypeDef *hdma);
+static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s);
+static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s);
+static uint32_t I2S_GetClockFreq(I2S_HandleTypeDef *hi2s);
+static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, uint32_t State, uint32_t Timeout);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup I2S_Exported_Functions I2S Exported Functions
+ * @{
+ */
+
+/** @defgroup I2S_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 I2Sx peripheral in simplex mode:
+
+ (+) User must Implement HAL_I2S_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_I2S_Init() to configure the selected device with
+ the selected configuration:
+ (++) Mode
+ (++) Standard
+ (++) Data Format
+ (++) MCLK Output
+ (++) Audio frequency
+ (++) Polarity
+ (++) Full duplex mode
+
+ (+) Call the function HAL_I2S_DeInit() to restore the default configuration
+ of the selected I2Sx peripheral.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the I2S according to the specified parameters
+ * in the I2S_InitTypeDef and create the associated handle.
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s)
+{
+ uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
+ uint32_t tmp = 0, i2sclk = 0;
+
+ /* Check the I2S handle allocation */
+ if(hi2s == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
+ assert_param(IS_I2S_MODE(hi2s->Init.Mode));
+ assert_param(IS_I2S_STANDARD(hi2s->Init.Standard));
+ assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat));
+ assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput));
+ assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq));
+ assert_param(IS_I2S_CPOL(hi2s->Init.CPOL));
+ assert_param(IS_I2S_CLOCKSOURCE(hi2s->Init.ClockSource));
+
+ if(hi2s->State == HAL_I2S_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hi2s->Lock = HAL_UNLOCKED;
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_I2S_MspInit(hi2s);
+ }
+
+ hi2s->State = HAL_I2S_STATE_BUSY;
+
+ /*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/
+ /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
+ hi2s->Instance->I2SCFGR &= ~(SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \
+ SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \
+ SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD);
+ hi2s->Instance->I2SPR = 0x0002;
+
+ /* Get the I2SCFGR register value */
+ tmpreg = hi2s->Instance->I2SCFGR;
+
+ /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/
+ if(hi2s->Init.AudioFreq == I2S_AUDIOFREQ_DEFAULT)
+ {
+ i2sodd = (uint16_t)0;
+ i2sdiv = (uint16_t)2;
+ }
+ /* If the requested audio frequency is not the default, compute the prescaler */
+ else
+ {
+ /* Check the frame length (For the Prescaler computing) *******************/
+ if(hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
+ {
+ /* Packet length is 16 bits */
+ packetlength = 1;
+ }
+ else
+ {
+ /* Packet length is 32 bits */
+ packetlength = 2;
+ }
+
+ /* Get I2S source Clock frequency ****************************************/
+
+ /* If an external I2S clock has to be used, the specific define should be set
+ in the project configuration or in the stm32f3xx_conf.h file */
+ if(hi2s->Init.ClockSource == I2S_CLOCK_EXTERNAL)
+ {
+ /* Set the I2S clock to the external clock value */
+ i2sclk = EXTERNAL_CLOCK_VALUE;
+ }
+ else
+ {
+ /* Get the I2S source clock value */
+ i2sclk = I2S_GetClockFreq(hi2s);
+ }
+
+ /* Compute the Real divider depending on the MCLK output state, with a floating point */
+ if(hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE)
+ {
+ /* MCLK output is enabled */
+ tmp = (uint16_t)(((((i2sclk / 256) * 10) / hi2s->Init.AudioFreq)) + 5);
+ }
+ else
+ {
+ /* MCLK output is disabled */
+ tmp = (uint16_t)(((((i2sclk / (32 * packetlength)) *10 ) / hi2s->Init.AudioFreq)) + 5);
+ }
+
+ /* Remove the flatting point */
+ tmp = tmp / 10;
+
+ /* Check the parity of the divider */
+ i2sodd = (uint16_t)(tmp & (uint16_t)0x0001);
+
+ /* Compute the i2sdiv prescaler */
+ i2sdiv = (uint16_t)((tmp - i2sodd) / 2);
+
+ /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
+ i2sodd = (uint16_t) (i2sodd << 8);
+ }
+
+ /* Test if the divider is 1 or 0 or greater than 0xFF */
+ if((i2sdiv < 2) || (i2sdiv > 0xFF))
+ {
+ /* Set the default values */
+ i2sdiv = 2;
+ i2sodd = 0;
+ }
+
+ /* Write to SPIx I2SPR register the computed value */
+ hi2s->Instance->I2SPR = (uint16_t)((uint16_t)i2sdiv | (uint16_t)(i2sodd | (uint16_t)hi2s->Init.MCLKOutput));
+
+ /* Configure the I2S with the I2S_InitStruct values */
+ tmpreg |= (uint16_t)((uint16_t)SPI_I2SCFGR_I2SMOD | (uint16_t)(hi2s->Init.Mode | \
+ (uint16_t)(hi2s->Init.Standard | (uint16_t)(hi2s->Init.DataFormat | \
+ (uint16_t)hi2s->Init.CPOL))));
+
+ /* Write to SPIx I2SCFGR */
+ hi2s->Instance->I2SCFGR = tmpreg;
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State= HAL_I2S_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the I2S peripheral
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s)
+{
+ /* Check the I2S handle allocation */
+ if(hi2s == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
+
+ hi2s->State = HAL_I2S_STATE_BUSY;
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_I2S_MspDeInit(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief I2S MSP Init
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+ __weak void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2S MSP DeInit
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+ __weak void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2S_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 I2S 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 I2S IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (#) Blocking mode functions are :
+ (++) HAL_I2S_Transmit()
+ (++) HAL_I2S_Receive()
+
+ (#) No-Blocking mode functions with Interrupt are :
+ (++) HAL_I2S_Transmit_IT()
+ (++) HAL_I2S_Receive_IT()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_I2S_Transmit_DMA()
+ (++) HAL_I2S_Receive_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_I2S_TxCpltCallback()
+ (++) HAL_I2S_RxCpltCallback()
+ (++) HAL_I2S_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData: a 16-bit pointer to data buffer.
+ * @param Size: number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @param Timeout: Timeout duration
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(hi2s->State == HAL_I2S_STATE_READY)
+ {
+ if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\
+ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B))
+ {
+ hi2s->TxXferSize = (Size << 1);
+ hi2s->TxXferCount = (Size << 1);
+ }
+ else
+ {
+ hi2s->TxXferSize = Size;
+ hi2s->TxXferCount = Size;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_BUSY_TX;
+
+ /* Check if the I2S is already enabled */
+ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ while(hi2s->TxXferCount > 0)
+ {
+ hi2s->Instance->DR = (*pData++);
+ hi2s->TxXferCount--;
+ /* Wait until TXE flag is set */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK)
+ {
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT;
+ HAL_I2S_ErrorCallback(hi2s);
+ return HAL_TIMEOUT;
+ }
+
+ /* Check if an underrun occurs */
+ if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET)
+ {
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_UDR;
+ HAL_I2S_ErrorCallback(hi2s);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Check if Slave mode is selected */
+ if(((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX) || ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX))
+ {
+ /* Wait until Busy flag is reset */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, Timeout) != HAL_OK)
+ {
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT;
+ HAL_I2S_ErrorCallback(hi2s);
+ return HAL_TIMEOUT;
+ }
+ }
+
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData: a 16-bit pointer to data buffer.
+ * @param Size: number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @param Timeout: Timeout duration
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate
+ * in continuous way and as the I2S is not disabled at the end of the I2S transaction.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(hi2s->State == HAL_I2S_STATE_READY)
+ {
+ if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\
+ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B))
+ {
+ hi2s->RxXferSize = (Size << 1);
+ hi2s->RxXferCount = (Size << 1);
+ }
+ else
+ {
+ hi2s->RxXferSize = Size;
+ hi2s->RxXferCount = Size;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_BUSY_RX;
+
+ /* Check if the I2S is already enabled */
+ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Check if Master Receiver mode is selected */
+ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX)
+ {
+ /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read
+ access to the SPI_SR register. */
+ __HAL_I2S_CLEAR_OVRFLAG(hi2s);
+ }
+
+ /* Receive data */
+ while(hi2s->RxXferCount > 0)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout) != HAL_OK)
+ {
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT;
+ HAL_I2S_ErrorCallback(hi2s);
+ return HAL_TIMEOUT;
+ }
+
+ /* Check if an overrun occurs */
+ if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET)
+ {
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_OVR;
+ HAL_I2S_ErrorCallback(hi2s);
+
+ return HAL_ERROR;
+ }
+
+ (*pData++) = hi2s->Instance->DR;
+ hi2s->RxXferCount--;
+ }
+
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData: a 16-bit pointer to data buffer.
+ * @param Size: number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ if(hi2s->State == HAL_I2S_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ hi2s->pTxBuffPtr = pData;
+ if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\
+ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B))
+ {
+ hi2s->TxXferSize = (Size << 1);
+ hi2s->TxXferCount = (Size << 1);
+ }
+ else
+ {
+ hi2s->TxXferSize = Size;
+ hi2s->TxXferCount = Size;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_BUSY_TX;
+
+ /* Enable TXE and ERR interrupt */
+ __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
+
+ /* Check if the I2S is already enabled */
+ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData: a 16-bit pointer to the Receive data buffer.
+ * @param Size: number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @note It is recommended to use DMA for the I2S receiver to avoid de-synchronisation
+ * between Master and Slave otherwise the I2S interrupt should be optimized.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ if(hi2s->State == HAL_I2S_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ hi2s->pRxBuffPtr = pData;
+ if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\
+ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B))
+ {
+ hi2s->RxXferSize = (Size << 1);
+ hi2s->RxXferCount = (Size << 1);
+ }
+ else
+ {
+ hi2s->RxXferSize = Size;
+ hi2s->RxXferCount = Size;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_BUSY_RX;
+
+ /* Enable TXE and ERR interrupt */
+ __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
+
+ /* Check if the I2S is already enabled */
+ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData: a 16-bit pointer to the Transmit data buffer.
+ * @param Size: number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ uint32_t *tmp;
+
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(hi2s->State == HAL_I2S_STATE_READY)
+ {
+ hi2s->pTxBuffPtr = pData;
+ if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\
+ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B))
+ {
+ hi2s->TxXferSize = (Size << 1);
+ hi2s->TxXferCount = (Size << 1);
+ }
+ else
+ {
+ hi2s->TxXferSize = Size;
+ hi2s->TxXferCount = Size;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_BUSY_TX;
+
+ /* Set the I2S Tx DMA Half transfer complete callback */
+ hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt;
+
+ /* Set the I2S TxDMA transfer complete callback */
+ hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt;
+
+ /* Set the DMA error callback */
+ hi2s->hdmatx->XferErrorCallback = I2S_DMAError;
+
+ /* Enable the Tx DMA Channel */
+ tmp = (uint32_t*)&pData;
+ HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t*)tmp, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize);
+
+ /* Check if the I2S is already enabled */
+ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Enable Tx DMA Request */
+ hi2s->Instance->CR2 |= SPI_CR2_TXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param pData: a 16-bit pointer to the Receive data buffer.
+ * @param Size: number of data sample to be sent:
+ * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
+ * configuration phase, the Size parameter means the number of 16-bit data length
+ * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
+ * the Size parameter means the number of 16-bit data length.
+ * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
+ * between Master and Slave(example: audio streaming).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
+{
+ uint32_t *tmp;
+
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ if(hi2s->State == HAL_I2S_STATE_READY)
+ {
+ hi2s->pRxBuffPtr = pData;
+ if(((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_24B)||\
+ ((hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)) == I2S_DATAFORMAT_32B))
+ {
+ hi2s->RxXferSize = (Size << 1);
+ hi2s->RxXferCount = (Size << 1);
+ }
+ else
+ {
+ hi2s->RxXferSize = Size;
+ hi2s->RxXferCount = Size;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
+ hi2s->State = HAL_I2S_STATE_BUSY_RX;
+
+ /* Set the I2S Rx DMA Half transfer complete callback */
+ hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
+
+ /* Set the I2S Rx DMA transfer complete callback */
+ hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
+
+ /* Set the DMA error callback */
+ hi2s->hdmarx->XferErrorCallback = I2S_DMAError;
+
+ /* Check if Master Receiver mode is selected */
+ if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX)
+ {
+ /* Clear the Overrun Flag by a read operation to the SPI_DR register followed by a read
+ access to the SPI_SR register. */
+ __HAL_I2S_CLEAR_OVRFLAG(hi2s);
+ }
+
+ /* Enable the Rx DMA Channel */
+ tmp = (uint32_t*)&pData;
+ HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, *(uint32_t*)tmp, hi2s->RxXferSize);
+
+ /* Check if the I2S is already enabled */
+ if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Enable Rx DMA Request */
+ hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Pauses the audio stream playing from the Media.
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s)
+{
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if(hi2s->State == HAL_I2S_STATE_BUSY_TX)
+ {
+ /* Disable the I2S DMA Tx request */
+ hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
+ }
+ else if(hi2s->State == HAL_I2S_STATE_BUSY_RX)
+ {
+ /* Disable the I2S DMA Rx request */
+ hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN);
+ }
+ else if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX)
+ {
+ if((hi2s->Init.Mode == I2S_MODE_SLAVE_TX)||(hi2s->Init.Mode == I2S_MODE_MASTER_TX))
+ {
+ /* Disable the I2S DMA Tx request */
+ hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
+ }
+ else
+ {
+ /* Disable the I2S DMA Rx request */
+ hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN);
+ }
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resumes the audio stream playing from the Media.
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s)
+{
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ if(hi2s->State == HAL_I2S_STATE_BUSY_TX)
+ {
+ /* Enable the I2S DMA Tx request */
+ SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
+ }
+ else if(hi2s->State == HAL_I2S_STATE_BUSY_RX)
+ {
+ /* Enable the I2S DMA Rx request */
+ SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
+ }
+
+ /* If the I2S peripheral is still not enabled, enable it */
+ if(HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
+ {
+ /* Enable I2S peripheral */
+ __HAL_I2S_ENABLE(hi2s);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the audio stream playing from the Media.
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s)
+{
+ /* Process Locked */
+ __HAL_LOCK(hi2s);
+
+ /* Disable the I2S Tx/Rx DMA requests */
+ CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
+ CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
+
+ /* Abort the I2S DMA Channel tx */
+ if(hi2s->hdmatx != NULL)
+ {
+ /* Disable the I2S DMA channel */
+ __HAL_DMA_DISABLE(hi2s->hdmatx);
+ HAL_DMA_Abort(hi2s->hdmatx);
+ }
+ /* Abort the I2S DMA Channel rx */
+ if(hi2s->hdmarx != NULL)
+ {
+ /* Disable the I2S DMA channel */
+ __HAL_DMA_DISABLE(hi2s->hdmarx);
+ HAL_DMA_Abort(hi2s->hdmarx);
+ }
+
+ /* Disable I2S peripheral */
+ __HAL_I2S_DISABLE(hi2s);
+
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2S interrupt request.
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL status
+ */
+void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s)
+{
+ __IO uint32_t i2ssr = hi2s->Instance->SR;
+
+ if(hi2s->State == HAL_I2S_STATE_BUSY_RX)
+ {
+ /* I2S in mode Receiver ----------------------------------------------------*/
+ if(((i2ssr & I2S_FLAG_RXNE) == I2S_FLAG_RXNE) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_RXNE) != RESET))
+ {
+ I2S_Receive_IT(hi2s);
+ }
+
+ /* I2S Overrun error interrupt occurred -------------------------------------*/
+ if(((i2ssr & I2S_FLAG_OVR) == I2S_FLAG_OVR) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR) != RESET))
+ {
+ /* Disable RXNE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
+
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_OVR;
+ HAL_I2S_ErrorCallback(hi2s);
+ }
+ }
+ else if(hi2s->State == HAL_I2S_STATE_BUSY_TX)
+ {
+ /* I2S in mode Transmitter ---------------------------------------------------*/
+ if(((i2ssr & I2S_FLAG_TXE) == I2S_FLAG_TXE) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_TXE) != RESET))
+ {
+ I2S_Transmit_IT(hi2s);
+ }
+
+ /* I2S Underrun error interrupt occurred ------------------------------------*/
+ if(((i2ssr & I2S_FLAG_UDR) == I2S_FLAG_UDR) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR) != RESET))
+ {
+ /* Disable TXE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
+
+ /* Set the I2S State ready */
+ hi2s->State = HAL_I2S_STATE_READY;
+
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_UDR;
+ HAL_I2S_ErrorCallback(hi2s);
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2S_Private_Functions I2S Private Functions
+ * @{
+ */
+/**
+ * @brief This function handles I2S Communication Timeout.
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @param Flag: Flag checked
+ * @param State: Value of the flag expected
+ * @param Timeout: Duration of the timeout
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag,
+ uint32_t State, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until flag is set */
+ if(State == RESET)
+ {
+ while(__HAL_I2S_GET_FLAG(hi2s, Flag) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* Set the I2S State ready */
+ hi2s->State= HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_I2S_GET_FLAG(hi2s, Flag) != RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ /* Set the I2S State ready */
+ hi2s->State= HAL_I2S_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2s);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+/** @addtogroup I2S_Exported_Functions I2S Exported Functions
+ * @{
+ */
+
+/** @addtogroup I2S_Exported_Functions_Group2 Input and Output operation functions
+ * @{
+ */
+/**
+ * @brief Tx Transfer Half completed callbacks
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+ __weak void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_TxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Transfer completed callbacks
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+ __weak void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer half completed callbacks
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callbacks
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+__weak void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2S error callbacks
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+ __weak void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_I2S_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2S_Exported_Functions_Group3 Peripheral State and Errors functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the I2S state
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval HAL state
+ */
+HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s)
+{
+ return hi2s->State;
+}
+
+/**
+ * @brief Return the I2S error code
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval I2S Error Code
+ */
+uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s)
+{
+ return hi2s->ErrorCode;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+ /**
+ * @brief Get I2S Input Clock based on I2S source clock selection
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module.
+ * @retval I2S Clock Input
+ */
+static uint32_t I2S_GetClockFreq(I2S_HandleTypeDef *hi2s)
+{
+ uint32_t tmpreg = 0;
+ /* This variable used to store the VCO Input (value in Hz) */
+ uint32_t vcoinput = 0;
+ /* This variable used to store the I2S_CK_x (value in Hz) */
+ uint32_t i2sclocksource = 0;
+
+ /* Configure I2S Clock based on I2S source clock selection */
+
+ /* I2S_CLK_x : I2S Block Clock configuration for different clock sources selected */
+ switch(hi2s->Init.ClockSource)
+ {
+ case I2S_CLOCK_SYSCLK :
+ {
+ /* Configure the PLLI2S division factor */
+ /* PLLI2S_VCO Input = PLL_SOURCE/PLLI2SM */
+ if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
+ {
+ /* In Case the PLL Source is HSI (Internal Clock) */
+ vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
+ }
+ else
+ {
+ /* In Case the PLL Source is HSE (External Clock) */
+ vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)));
+ }
+
+ /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
+ /* I2S_CLK(first level) = PLLI2S_VCO Output/PLLI2SR */
+ tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28;
+ i2sclocksource = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6))/(tmpreg);
+
+ break;
+ }
+ case I2S_CLOCK_EXTERNAL :
+ {
+ i2sclocksource = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+ default :
+ {
+ break;
+ }
+ }
+
+ /* the return result is the value of I2S clock */
+ return i2sclocksource;
+}
+
+/** @addtogroup I2S_Private_Functions I2S Private Functions
+ * @{
+ */
+/**
+ * @brief DMA I2S 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 I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
+ {
+ hi2s->TxXferCount = 0;
+
+ /* Disable Tx DMA Request */
+ hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
+
+ if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX)
+ {
+ if(hi2s->RxXferCount == 0)
+ {
+ hi2s->State = HAL_I2S_STATE_READY;
+ }
+ }
+ else
+ {
+ hi2s->State = HAL_I2S_STATE_READY;
+ }
+ }
+ HAL_I2S_TxCpltCallback(hi2s);
+}
+
+/**
+ * @brief DMA I2S transmit process half complete callback
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ HAL_I2S_TxHalfCpltCallback(hi2s);
+}
+
+/**
+ * @brief DMA I2S 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 I2S_DMARxCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
+ {
+ /* Disable Rx DMA Request */
+ hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN);
+
+ hi2s->RxXferCount = 0;
+ if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX)
+ {
+ if(hi2s->TxXferCount == 0)
+ {
+ hi2s->State = HAL_I2S_STATE_READY;
+ }
+ }
+ else
+ {
+ hi2s->State = HAL_I2S_STATE_READY;
+ }
+ }
+ HAL_I2S_RxCpltCallback(hi2s);
+}
+
+/**
+ * @brief DMA I2S receive process half complete callback
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
+
+ HAL_I2S_RxHalfCpltCallback(hi2s);
+}
+
+/**
+ * @brief DMA I2S 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 I2S_DMAError(DMA_HandleTypeDef *hdma)
+{
+ I2S_HandleTypeDef* hi2s = ( I2S_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* Disable Rx and Tx DMA Request */
+ hi2s->Instance->CR2 &= (uint32_t)(~(SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN));
+ hi2s->TxXferCount = 0;
+ hi2s->RxXferCount = 0;
+
+ hi2s->State= HAL_I2S_STATE_READY;
+
+ /* Set the error code and execute error callback*/
+ hi2s->ErrorCode |= HAL_I2S_ERROR_DMA;
+ HAL_I2S_ErrorCallback(hi2s);
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt
+ * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains
+ * the configuration information for I2S module
+ * @retval None
+ */
+static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s)
+{
+ /* Transmit data */
+ hi2s->Instance->DR = (*hi2s->pTxBuffPtr++);
+ hi2s->TxXferCount--;
+
+ if(hi2s->TxXferCount == 0)
+ {
+ /* Disable TXE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ HAL_I2S_TxCpltCallback(hi2s);
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt
+ * @param hi2s: I2S handle
+ * @retval None
+ */
+static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s)
+{
+ /* Receive data */
+ (*hi2s->pRxBuffPtr++) = hi2s->Instance->DR;
+ hi2s->RxXferCount--;
+
+ if(hi2s->RxXferCount == 0)
+ {
+ /* Disable RXNE and ERR interrupt */
+ __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
+
+ hi2s->State = HAL_I2S_STATE_READY;
+ HAL_I2S_RxCpltCallback(hi2s);
+ }
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_I2S_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_pcd.c b/stmhal/hal/f7/src/stm32f7xx_hal_pcd.c
new file mode 100644
index 0000000000..1e132b9e82
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_pcd.c
@@ -0,0 +1,1202 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_pcd.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 HCD 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
+ (+++) __OTGFS-OTG_CLK_ENABLE()/__OTGHS-OTG_CLK_ENABLE();
+ (+++) __OTGHSULPI_CLK_ENABLE(); (For High Speed Mode)
+
+ (##) 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 HCD transmission and reception:
+ (##) HAL_PCD_Start();
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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 create 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));
+
+ hpcd->State = HAL_PCD_STATE_BUSY;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_PCD_MspInit(hpcd);
+
+ /* 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 < 15 ; 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 < 15 ; 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);
+ }
+
+ 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)
+{
+ /* 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)
+{
+ /* 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 IO 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 This function 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(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);
+ }
+ }
+ }
+
+ 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;
+
+ if ( USB_GetDevSpeed(hpcd->Instance) == USB_OTG_SPEED_HIGH)
+ {
+ hpcd->Init.speed = USB_OTG_SPEED_HIGH;
+ hpcd->Init.ep0_mps = USB_OTG_HS_MAX_PACKET_SIZE ;
+ hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_HS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
+ }
+ else
+ {
+ 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 callbacks
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+ __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t 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 callbacks
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+ __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t 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)
+{
+ /* 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 callbacks
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+ __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *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 callbacks
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+ __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *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 callbacks
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+ __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *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 callbacks
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+ __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *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 callbacks
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+ __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t 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 callbacks
+ * @param hpcd: PCD handle
+ * @param epnum: endpoint number
+ * @retval None
+ */
+ __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t 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 callbacks
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+ __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *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 callbacks
+ * @param hpcd: PCD handle
+ * @retval None
+ */
+ __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *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 HAL_PCD_ActivateRemoteWakeup : Active remote wake-up 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 wake-up signaling */
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief HAL_PCD_DeActivateRemoteWakeup : de-active remote wake-up 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 wake-up 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 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 DCD_WriteEmptyTxFifo
+ * 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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_pcd_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_pcd_ex.c
new file mode 100644
index 0000000000..69b0d5ad13
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_pcd_ex.c
@@ -0,0 +1,197 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_pcd_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief PCD 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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 HAL_PCDEx_ActivateLPM : active 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 HAL_PCDEx_DeActivateLPM : de-active 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 HAL_PCDEx_LPM_Callback : Send LPM message to user layer
+ * @param hpcd: PCD handle
+ * @param msg: LPM message
+ * @retval HAL status
+ */
+__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
+{
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PCD_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_pwr.c b/stmhal/hal/f7/src/stm32f7xx_hal_pwr.c
new file mode 100644
index 0000000000..6d7d5660b4
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_pwr.c
@@ -0,0 +1,609 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_pwr.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Power Controller (PWR) peripheral:
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PWR PWR
+ * @brief PWR HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup PWR_Private_Constants
+ * @{
+ */
+
+/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask
+ * @{
+ */
+#define PVD_MODE_IT ((uint32_t)0x00010000)
+#define PVD_MODE_EVT ((uint32_t)0x00020000)
+#define PVD_RISING_EDGE ((uint32_t)0x00000001)
+#define PVD_FALLING_EDGE ((uint32_t)0x00000002)
+/**
+ * @}
+ */
+
+/** @defgroup PWR_ENABLE_WUP_Mask PWR Enable WUP Mask
+ * @{
+ */
+#define PWR_EWUP_MASK ((uint32_t)0x00003F00)
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private 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 #####
+ ===============================================================================
+ [..]
+ 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:
+ (+) Enable the Power Controller (PWR) APB1 interface clock using the
+ __HAL_RCC_PWR_CLK_ENABLE() macro.
+ (+) Enable access to RTC domain using the HAL_PWR_EnableBkUpAccess() function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes 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 Enables access to the backup domain (RTC registers, RTC
+ * backup data registers and backup SRAM).
+ * @note If the HSE divided by 2, 3, ..31 is used as the RTC clock, the
+ * Backup Domain Access should be kept enabled.
+ * @retval None
+ */
+void HAL_PWR_EnableBkUpAccess(void)
+{
+ /* Enable access to RTC and backup registers */
+ SET_BIT(PWR->CR1, PWR_CR1_DBP);
+}
+
+/**
+ * @brief Disables access to the backup domain (RTC registers, RTC
+ * backup data registers and backup SRAM).
+ * @note If the HSE divided by 2, 3, ..31 is used as the RTC clock, the
+ * Backup Domain Access should be kept enabled.
+ * @retval None
+ */
+void HAL_PWR_DisableBkUpAccess(void)
+{
+ /* Disable access to RTC and backup registers */
+ 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 the PWR_CR).
+ (+) A 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_PWR_PVD_EXTI_ENABLE_IT() macro.
+ (+) The PVD is stopped in Standby mode.
+
+ *** Wake-up pin configuration ***
+ ================================
+ [..]
+ (+) Wake-up pin is used to wake up the system from Standby mode. This pin is
+ forced in input pull-down configuration and is active on rising edges.
+ (+) There are to 6 Wake-up pin in the STM32F7 devices family
+
+ *** Low Power modes configuration ***
+ =====================================
+ [..]
+ The devices feature 3 low-power modes:
+ (+) Sleep mode: Cortex-M7 core stopped, peripherals kept running.
+ (+) Stop mode: all clocks are stopped, regulator running, regulator
+ in low power mode
+ (+) Standby mode: 1.2V domain powered off.
+
+ *** Sleep mode ***
+ ==================
+ [..]
+ (+) Entry:
+ The Sleep mode is entered by using the HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI)
+ functions with
+ (++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
+ (++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
+
+ -@@- The Regulator parameter is not used for the STM32F7 family
+ and is kept as parameter just to maintain compatibility with the
+ lower power families (STM32L).
+ (+) Exit:
+ Any peripheral interrupt acknowledged by the nested vectored interrupt
+ controller (NVIC) can wake up the device from Sleep mode.
+
+ *** Stop mode ***
+ =================
+ [..]
+ In Stop mode, all clocks in the 1.2V domain are stopped, the PLL, the HSI,
+ and the HSE RC oscillators are disabled. Internal SRAM and register contents
+ are preserved.
+ The voltage regulator can be configured either in normal or low-power mode.
+ To minimize the consumption In Stop mode, FLASH can be powered off before
+ entering the Stop mode using the HAL_PWREx_EnableFlashPowerDown() function.
+ It can be switched on again by software after exiting the Stop mode using
+ the HAL_PWREx_DisableFlashPowerDown() function.
+
+ (+) Entry:
+ The Stop mode is entered using the HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON)
+ function with:
+ (++) Main regulator ON.
+ (++) Low Power regulator ON.
+ (+) Exit:
+ Any EXTI Line (Internal or External) configured in Interrupt/Event mode.
+
+ *** Standby mode ***
+ ====================
+ [..]
+ (+)
+ The Standby mode allows to achieve the lowest power consumption. It is based
+ on the Cortex-M7 deep sleep mode, with the voltage regulator disabled.
+ The 1.2V domain is consequently powered off. The PLL, the HSI oscillator and
+ the HSE oscillator are also switched off. SRAM and register contents are lost
+ except for the RTC registers, RTC backup registers, backup SRAM and Standby
+ circuitry.
+
+ The voltage regulator is OFF.
+
+ (++) Entry:
+ (+++) The Standby mode is entered using the HAL_PWR_EnterSTANDBYMode() function.
+ (++) Exit:
+ (+++) WKUP pin rising or falling edge, RTC alarm (Alarm A and Alarm B), RTC
+ wakeup, tamper event, time stamp event, external reset in NRST pin, IWDG 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 and Standby 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 Configures the voltage threshold detected by the Power Voltage Detector(PVD).
+ * @param sConfigPVD: pointer to an PWR_PVDTypeDef structure that contains the configuration
+ * information for the PVD.
+ * @note Refer to the electrical characteristics of your device datasheet for
+ * more details about the voltage threshold corresponding to each
+ * detection level.
+ * @retval None
+ */
+void 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[7:5] bits according to PVDLevel value */
+ MODIFY_REG(PWR->CR1, PWR_CR1_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_RISING_EDGE();
+ __HAL_PWR_PVD_EXTI_DISABLE_FALLING_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();
+ }
+}
+
+/**
+ * @brief Enables the Power Voltage Detector(PVD).
+ * @retval None
+ */
+void HAL_PWR_EnablePVD(void)
+{
+ /* Enable the power voltage detector */
+ SET_BIT(PWR->CR1, PWR_CR1_PVDE);
+}
+
+/**
+ * @brief Disables the Power Voltage Detector(PVD).
+ * @retval None
+ */
+void HAL_PWR_DisablePVD(void)
+{
+ /* Disable the power voltage detector */
+ CLEAR_BIT(PWR->CR1, PWR_CR1_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 sets the default polarity:
+ * detection on high level (rising edge):
+ * @arg PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5, PWR_WAKEUP_PIN6
+ * or one of the following value where the user can explicitly states the enabled pin and
+ * the chosen polarity
+ * @arg PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW
+ * @arg PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW
+ * @arg PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW
+ * @arg PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW
+ * @arg PWR_WAKEUP_PIN5_HIGH or PWR_WAKEUP_PIN5_LOW
+ * @arg PWR_WAKEUP_PIN6_HIGH or PWR_WAKEUP_PIN6_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));
+
+ /* Enable wake-up pin */
+ SET_BIT(PWR->CSR2, (PWR_EWUP_MASK & WakeUpPinPolarity));
+
+ /* Specifies the Wake-Up pin polarity for the event detection
+ (rising or falling edge) */
+ MODIFY_REG(PWR->CR2, (PWR_EWUP_MASK & WakeUpPinPolarity), (WakeUpPinPolarity >> 0x06));
+}
+
+/**
+ * @brief Disables the WakeUp PINx functionality.
+ * @param WakeUpPinx: Specifies the Power Wake-Up pin to disable.
+ * This parameter can be one of the following values:
+ * @arg PWR_WAKEUP_PIN1
+ * @arg PWR_WAKEUP_PIN2
+ * @arg PWR_WAKEUP_PIN3
+ * @arg PWR_WAKEUP_PIN4
+ * @arg PWR_WAKEUP_PIN5
+ * @arg PWR_WAKEUP_PIN6
+ * @retval None
+ */
+void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx)
+{
+ assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx));
+
+ CLEAR_BIT(PWR->CSR2, WakeUpPinx);
+}
+
+/**
+ * @brief Enters Sleep mode.
+ *
+ * @note In Sleep mode, all I/O pins keep the same state as in Run mode.
+ *
+ * @note In Sleep mode, the systick is stopped to avoid exit from this mode with
+ * systick interrupt when used as time base for Timeout
+ *
+ * @param Regulator: Specifies the regulator state in SLEEP mode.
+ * This parameter can be one of the following values:
+ * @arg PWR_MAINREGULATOR_ON: SLEEP mode with regulator ON
+ * @arg PWR_LOWPOWERREGULATOR_ON: SLEEP mode with low power regulator ON
+ * @note This parameter is not used for the STM32F7 family and is kept as parameter
+ * just to maintain compatibility with the lower power families.
+ * @param SLEEPEntry: Specifies if SLEEP mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
+ * @arg PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
+ * @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));
+
+ /* 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 Enters Stop mode.
+ * @note In Stop mode, all I/O pins keep the same state as in Run mode.
+ * @note When exiting Stop mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock.
+ * @note When the voltage regulator operates in low power mode, an additional
+ * startup delay is incurred when waking up from Stop mode.
+ * By keeping the internal regulator ON during Stop mode, 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 PWR_MAINREGULATOR_ON: Stop mode with regulator ON
+ * @arg PWR_LOWPOWERREGULATOR_ON: Stop mode with low power regulator ON
+ * @param STOPEntry: Specifies if Stop mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg PWR_STOPENTRY_WFI: Enter Stop mode with WFI instruction
+ * @arg PWR_STOPENTRY_WFE: Enter Stop mode with WFE instruction
+ * @retval None
+ */
+void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
+{
+ uint32_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_PWR_REGULATOR(Regulator));
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Select the regulator state in Stop mode ---------------------------------*/
+ tmpreg = PWR->CR1;
+ /* Clear PDDS and LPDS bits */
+ tmpreg &= (uint32_t)~(PWR_CR1_PDDS | PWR_CR1_LPDS);
+
+ /* Set LPDS, MRLVDS and LPLVDS bits according to Regulator value */
+ tmpreg |= Regulator;
+
+ /* Store the new value */
+ PWR->CR1 = tmpreg;
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SCB->SCR |= 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 */
+ SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
+}
+
+/**
+ * @brief Enters Standby mode.
+ * @note In Standby mode, all I/O pins are high impedance except for:
+ * - Reset pad (still available)
+ * - RTC_AF1 pin (PC13) if configured for tamper, time-stamp, RTC
+ * Alarm out, or RTC clock calibration out.
+ * - RTC_AF2 pin (PI8) if configured for tamper or time-stamp.
+ * - WKUP pins if enabled.
+ * @retval None
+ */
+void HAL_PWR_EnterSTANDBYMode(void)
+{
+ /* Select Standby mode */
+ PWR->CR1 |= PWR_CR1_PDDS;
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SCB->SCR |= 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 interrupt request.
+ * @note This API should be called under the PVD_IRQHandler().
+ * @retval None
+ */
+void HAL_PWR_PVD_IRQHandler(void)
+{
+ /* Check PWR Exti flag */
+ if(__HAL_PWR_PVD_EXTI_GET_FLAG() != RESET)
+ {
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback();
+
+ /* Clear PWR Exti pending bit */
+ __HAL_PWR_PVD_EXTI_CLEAR_FLAG();
+ }
+}
+
+/**
+ * @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 could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Indicates 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 Disables Sleep-On-Exit feature when returning from Handler mode to Thread mode.
+ * @note Clears 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 Enables CORTEX M4 SEVONPEND bit.
+ * @note Sets 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 Disables CORTEX M4 SEVONPEND bit.
+ * @note Clears 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));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_pwr_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_pwr_ex.c
new file mode 100644
index 0000000000..19ca4c8ce3
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_pwr_ex.c
@@ -0,0 +1,564 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_pwr_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief Extended PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of PWR extension peripheral:
+ * + Peripheral Extended features functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PWREx PWREx
+ * @brief PWR HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup PWREx_Private_Constants
+ * @{
+ */
+#define PWR_OVERDRIVE_TIMEOUT_VALUE 1000
+#define PWR_UDERDRIVE_TIMEOUT_VALUE 1000
+#define PWR_BKPREG_TIMEOUT_VALUE 1000
+#define PWR_VOSRDY_TIMEOUT_VALUE 1000
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup PWREx_Exported_Functions PWREx Exported Functions
+ * @{
+ */
+
+/** @defgroup PWREx_Exported_Functions_Group1 Peripheral Extended features functions
+ * @brief Peripheral Extended features functions
+ *
+@verbatim
+
+ ===============================================================================
+ ##### Peripheral extended features functions #####
+ ===============================================================================
+
+ *** Main and Backup Regulators configuration ***
+ ================================================
+ [..]
+ (+) The backup domain includes 4 Kbytes of backup SRAM accessible only from
+ the CPU, and address in 32-bit, 16-bit or 8-bit mode. Its content is
+ retained even in Standby or VBAT mode when the low power backup regulator
+ is enabled. It can be considered as an internal EEPROM when VBAT is
+ always present. You can use the HAL_PWREx_EnableBkUpReg() function to
+ enable the low power backup regulator.
+
+ (+) When the backup domain is supplied by VDD (analog switch connected to VDD)
+ the backup SRAM is powered from VDD which replaces the VBAT power supply to
+ save battery life.
+
+ (+) The backup SRAM is not mass erased by a tamper event. It is read
+ protected to prevent confidential data, such as cryptographic private
+ key, from being accessed. The backup SRAM can be erased only through
+ the Flash interface when a protection level change from level 1 to
+ level 0 is requested.
+ -@- Refer to the description of Read protection (RDP) in the Flash
+ programming manual.
+
+ (+) The main internal regulator can be configured to have a tradeoff between
+ performance and power consumption when the device does not operate at
+ the maximum frequency. This is done through __HAL_PWR_MAINREGULATORMODE_CONFIG()
+ macro which configure VOS bit in PWR_CR register
+
+ Refer to the product datasheets for more details.
+
+ *** FLASH Power Down configuration ****
+ =======================================
+ [..]
+ (+) By setting the FPDS bit in the PWR_CR register by using the
+ HAL_PWREx_EnableFlashPowerDown() function, the Flash memory also enters power
+ down mode when the device enters Stop mode. When the Flash memory
+ is in power down mode, an additional startup delay is incurred when
+ waking up from Stop mode.
+
+ *** Over-Drive and Under-Drive configuration ****
+ =================================================
+ [..]
+ (+) In Run mode: the main regulator has 2 operating modes available:
+ (++) Normal mode: The CPU and core logic operate at maximum frequency at a given
+ voltage scaling (scale 1, scale 2 or scale 3)
+ (++) Over-drive mode: This mode allows the CPU and the core logic to operate at a
+ higher frequency than the normal mode for a given voltage scaling (scale 1,
+ scale 2 or scale 3). This mode is enabled through HAL_PWREx_EnableOverDrive() function and
+ disabled by HAL_PWREx_DisableOverDrive() function, to enter or exit from Over-drive mode please follow
+ the sequence described in Reference manual.
+
+ (+) In Stop mode: the main regulator or low power regulator supplies a low power
+ voltage to the 1.2V domain, thus preserving the content of registers
+ and internal SRAM. 2 operating modes are available:
+ (++) Normal mode: the 1.2V domain is preserved in nominal leakage mode. This mode is only
+ available when the main regulator or the low power regulator is used in Scale 3 or
+ low voltage mode.
+ (++) Under-drive mode: the 1.2V domain is preserved in reduced leakage mode. This mode is only
+ available when the main regulator or the low power regulator is in low voltage mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the Backup Regulator.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableBkUpReg(void)
+{
+ uint32_t tickstart = 0;
+
+ /* Enable Backup regulator */
+ PWR->CSR1 |= PWR_CSR1_BRE;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till Backup regulator ready flag is set */
+ while(__HAL_PWR_GET_FLAG(PWR_FLAG_BRR) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_BKPREG_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables the Backup Regulator.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableBkUpReg(void)
+{
+ uint32_t tickstart = 0;
+
+ /* Disable Backup regulator */
+ PWR->CSR1 &= (uint32_t)~((uint32_t)PWR_CSR1_BRE);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till Backup regulator ready flag is set */
+ while(__HAL_PWR_GET_FLAG(PWR_FLAG_BRR) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_BKPREG_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables the Flash Power Down in Stop mode.
+ * @retval None
+ */
+void HAL_PWREx_EnableFlashPowerDown(void)
+{
+ /* Enable the Flash Power Down */
+ PWR->CR1 |= PWR_CR1_FPDS;
+}
+
+/**
+ * @brief Disables the Flash Power Down in Stop mode.
+ * @retval None
+ */
+void HAL_PWREx_DisableFlashPowerDown(void)
+{
+ /* Disable the Flash Power Down */
+ PWR->CR1 &= (uint32_t)~((uint32_t)PWR_CR1_FPDS);
+}
+
+/**
+ * @brief Enables Main Regulator low voltage mode.
+ * @retval None
+ */
+void HAL_PWREx_EnableMainRegulatorLowVoltage(void)
+{
+ /* Enable Main regulator low voltage */
+ PWR->CR1 |= PWR_CR1_MRUDS;
+}
+
+/**
+ * @brief Disables Main Regulator low voltage mode.
+ * @retval None
+ */
+void HAL_PWREx_DisableMainRegulatorLowVoltage(void)
+{
+ /* Disable Main regulator low voltage */
+ PWR->CR1 &= (uint32_t)~((uint32_t)PWR_CR1_MRUDS);
+}
+
+/**
+ * @brief Enables Low Power Regulator low voltage mode.
+ * @retval None
+ */
+void HAL_PWREx_EnableLowRegulatorLowVoltage(void)
+{
+ /* Enable low power regulator */
+ PWR->CR1 |= PWR_CR1_LPUDS;
+}
+
+/**
+ * @brief Disables Low Power Regulator low voltage mode.
+ * @retval None
+ */
+void HAL_PWREx_DisableLowRegulatorLowVoltage(void)
+{
+ /* Disable low power regulator */
+ PWR->CR1 &= (uint32_t)~((uint32_t)PWR_CR1_LPUDS);
+}
+
+/**
+ * @brief Activates the Over-Drive mode.
+ * @note This mode allows the CPU and the core logic to operate at a higher frequency
+ * than the normal mode for a given voltage scaling (scale 1, scale 2 or scale 3).
+ * @note It is recommended to enter or exit Over-drive mode when the application is not running
+ * critical tasks and when the system clock source is either HSI or HSE.
+ * During the Over-drive switch activation, no peripheral clocks should be enabled.
+ * The peripheral clocks must be enabled once the Over-drive mode is activated.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableOverDrive(void)
+{
+ uint32_t tickstart = 0;
+
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* Enable the Over-drive to extend the clock frequency to 216 MHz */
+ __HAL_PWR_OVERDRIVE_ENABLE();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(!__HAL_PWR_GET_FLAG(PWR_FLAG_ODRDY))
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_OVERDRIVE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Enable the Over-drive switch */
+ __HAL_PWR_OVERDRIVESWITCHING_ENABLE();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(!__HAL_PWR_GET_FLAG(PWR_FLAG_ODSWRDY))
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_OVERDRIVE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates the Over-Drive mode.
+ * @note This mode allows the CPU and the core logic to operate at a higher frequency
+ * than the normal mode for a given voltage scaling (scale 1, scale 2 or scale 3).
+ * @note It is recommended to enter or exit Over-drive mode when the application is not running
+ * critical tasks and when the system clock source is either HSI or HSE.
+ * During the Over-drive switch activation, no peripheral clocks should be enabled.
+ * The peripheral clocks must be enabled once the Over-drive mode is activated.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableOverDrive(void)
+{
+ uint32_t tickstart = 0;
+
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* Disable the Over-drive switch */
+ __HAL_PWR_OVERDRIVESWITCHING_DISABLE();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_PWR_GET_FLAG(PWR_FLAG_ODSWRDY))
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_OVERDRIVE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Disable the Over-drive */
+ __HAL_PWR_OVERDRIVE_DISABLE();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_PWR_GET_FLAG(PWR_FLAG_ODRDY))
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_OVERDRIVE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enters in Under-Drive STOP mode.
+ *
+ * @note This mode can be selected only when the Under-Drive is already active
+ *
+ * @note This mode is enabled only with STOP low power mode.
+ * In this mode, the 1.2V domain is preserved in reduced leakage mode. This
+ * mode is only available when the main regulator or the low power regulator
+ * is in low voltage mode
+ *
+ * @note If the Under-drive mode was enabled, it is automatically disabled after
+ * exiting Stop mode.
+ * When the voltage regulator operates in Under-drive mode, an additional
+ * startup delay is induced when waking up from Stop mode.
+ *
+ * @note In Stop mode, all I/O pins keep the same state as in Run mode.
+ *
+ * @note When exiting Stop mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock.
+ *
+ * @note When the voltage regulator operates in low power mode, an additional
+ * startup delay is incurred when waking up from Stop mode.
+ * By keeping the internal regulator ON during Stop mode, 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 PWR_MAINREGULATOR_UNDERDRIVE_ON: Main Regulator in under-drive mode
+ * and Flash memory in power-down when the device is in Stop under-drive mode
+ * @arg PWR_LOWPOWERREGULATOR_UNDERDRIVE_ON: Low Power Regulator in under-drive mode
+ * and Flash memory in power-down when the device is in Stop under-drive mode
+ * @param STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.
+ * This parameter can be one of the following values:
+ * @arg PWR_SLEEPENTRY_WFI: enter STOP mode with WFI instruction
+ * @arg PWR_SLEEPENTRY_WFE: enter STOP mode with WFE instruction
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_PWREx_EnterUnderDriveSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
+{
+ uint32_t tempreg = 0;
+ uint32_t tickstart = 0;
+
+ /* Check the parameters */
+ assert_param(IS_PWR_REGULATOR_UNDERDRIVE(Regulator));
+ assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
+
+ /* Enable Power ctrl clock */
+ __HAL_RCC_PWR_CLK_ENABLE();
+ /* Enable the Under-drive Mode ---------------------------------------------*/
+ /* Clear Under-drive flag */
+ __HAL_PWR_CLEAR_ODRUDR_FLAG();
+
+ /* Enable the Under-drive */
+ __HAL_PWR_UNDERDRIVE_ENABLE();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait for UnderDrive mode is ready */
+ while(__HAL_PWR_GET_FLAG(PWR_FLAG_UDRDY))
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_UDERDRIVE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Select the regulator state in STOP mode ---------------------------------*/
+ tempreg = PWR->CR1;
+ /* Clear PDDS, LPDS, MRLUDS and LPLUDS bits */
+ tempreg &= (uint32_t)~(PWR_CR1_PDDS | PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_MRUDS);
+
+ /* Set LPDS, MRLUDS and LPLUDS bits according to PWR_Regulator value */
+ tempreg |= Regulator;
+
+ /* Store the new value */
+ PWR->CR1 = tempreg;
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+ /* Select STOP mode entry --------------------------------------------------*/
+ if(STOPEntry == PWR_SLEEPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __WFE();
+ }
+ /* Reset SLEEPDEEP bit of Cortex System Control Register */
+ SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Returns Voltage Scaling Range.
+ * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_SCALE1, PWR_REGULATOR_VOLTAGE_SCALE2 or
+ * PWR_REGULATOR_VOLTAGE_SCALE3)PWR_REGULATOR_VOLTAGE_SCALE1
+ */
+uint32_t HAL_PWREx_GetVoltageRange(void)
+{
+ return (PWR->CR1 & PWR_CR1_VOS);
+}
+
+/**
+ * @brief Configures 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 PWR_REGULATOR_VOLTAGE_SCALE1: Regulator voltage output range 1 mode,
+ * typical output voltage at 1.4 V,
+ * system frequency up to 216 MHz.
+ * @arg PWR_REGULATOR_VOLTAGE_SCALE2: Regulator voltage output range 2 mode,
+ * typical output voltage at 1.2 V,
+ * system frequency up to 180 MHz.
+ * @arg PWR_REGULATOR_VOLTAGE_SCALE3: Regulator voltage output range 2 mode,
+ * typical output voltage at 1.00 V,
+ * system frequency up to 151 MHz.
+ * @note To update the system clock frequency(SYSCLK):
+ * - Set the HSI or HSE as system clock frequency using the HAL_RCC_ClockConfig().
+ * - Call the HAL_RCC_OscConfig() to configure the PLL.
+ * - Call HAL_PWREx_ConfigVoltageScaling() API to adjust the voltage scale.
+ * - Set the new system clock frequency using the HAL_RCC_ClockConfig().
+ * @note The scale can be modified only when the HSI or HSE clock source is selected
+ * as system clock source, otherwise the API returns HAL_ERROR.
+ * @note When the PLL is OFF, the voltage scale 3 is automatically selected and the VOS bits
+ * value in the PWR_CR1 register are not taken in account.
+ * @note This API forces the PLL state ON to allow the possibility to configure the voltage scale 1 or 2.
+ * @note The new voltage scale is active only when the PLL is ON.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling)
+{
+ uint32_t tickstart = 0;
+
+ assert_param(IS_PWR_REGULATOR_VOLTAGE(VoltageScaling));
+
+ /* Enable Power ctrl clock */
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* Check if the PLL is used as system clock or not */
+ if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
+ {
+ /* Disable the main PLL */
+ __HAL_RCC_PLL_DISABLE();
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+ /* Wait till PLL is disabled */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set Range */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(VoltageScaling);
+
+ /* Enable the main PLL */
+ __HAL_RCC_PLL_ENABLE();
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+ /* Wait till PLL is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+ while((__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY) == RESET))
+ {
+ if((HAL_GetTick() - tickstart ) > PWR_VOSRDY_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_rcc.c b/stmhal/hal/f7/src/stm32f7xx_hal_rcc.c
new file mode 100644
index 0000000000..e131f4ef11
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_rcc.c
@@ -0,0 +1,1197 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_rcc.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 Internal High Speed oscillator
+ (HSI 16MHz) 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 (AHB) and Low speed (APB) busses;
+ all peripherals mapped on these busses are running at HSI speed.
+ (+) The clock for all peripherals is switched off, except the SRAM and FLASH.
+ (+) All GPIOs are in input floating state, 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 (I2S, RTC, ADC, USB OTG FS/SDIO/RNG)
+
+ ##### RCC Limitations #####
+ ==============================================================================
+ [..]
+ A delay between an RCC peripheral clock enable and the effective peripheral
+ enabling should be taken into account in order to manage the peripheral read/write
+ from/to registers.
+ (+) This delay depends on the peripheral mapping.
+ (+) If peripheral is mapped on AHB: the delay is 2 AHB clock cycle
+ after the clock enable bit is set on the hardware register
+ (+) If peripheral is mapped on APB: the delay is 2 APB clock cycle
+ after the clock enable bit is set on the hardware register
+
+ [..]
+ Implemented Workaround:
+ (+) For AHB & APB peripherals, a dummy read to the peripheral register has been
+ inserted in each __HAL_RCC_PPP_CLK_ENABLE() macro.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RCC RCC
+ * @brief RCC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* 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 MCO2_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
+#define MCO2_GPIO_PORT GPIOC
+#define MCO2_PIN GPIO_PIN_9
+
+/**
+ * @}
+ */
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup RCC_Private_Variables RCC Private Variables
+ * @{
+ */
+const uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/* 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/external oscillators
+ (HSE, HSI, LSE, LSI, PLL, CSS and MCO) and the System buses 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.
+
+ (#) LSI (low-speed internal), 32 KHz low consumption RC used as IWDG and/or RTC
+ clock source.
+
+ (#) HSE (high-speed external), 4 to 26 MHz crystal oscillator used directly or
+ through the PLL as System clock source. Can be used also as RTC clock source.
+
+ (#) LSE (low-speed external), 32 KHz oscillator used as RTC clock source.
+
+ (#) PLL (clocked by HSI or HSE), featuring two different output clocks:
+ (++) The first output is used to generate the high speed system clock (up to 216 MHz)
+ (++) The second output is used to generate the clock for the USB OTG FS (48 MHz),
+ the random analog generator (<=48 MHz) and the SDIO (<= 48 MHz).
+
+ (#) CSS (Clock security system), once enable using the function HAL_RCC_EnableCSS()
+ and 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-M7 NMI
+ (Non-Maskable Interrupt) exception vector.
+
+ (#) MCO1 (microcontroller clock output), used to output HSI, LSE, HSE or PLL
+ clock (through a configurable prescaler) on PA8 pin.
+
+ (#) MCO2 (microcontroller clock output), used to output HSE, PLL, SYSCLK or PLLI2S
+ clock (through a configurable prescaler) on PC9 pin.
+
+ [..] System, AHB and APB busses clocks configuration
+ (#) Several clock sources can be used to drive the System clock (SYSCLK): HSI,
+ HSE and 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:
+ (+@) I2S: the I2S clock can be derived either from a specific PLL (PLLI2S) or
+ from an external clock mapped on the I2S_CKIN pin.
+ You have to use __HAL_RCC_PLLI2S_CONFIG() macro to configure this clock.
+ (+@) SAI: the SAI clock can be derived either from a specific PLL (PLLI2S) or (PLLSAI) or
+ from an external clock mapped on the I2S_CKIN pin.
+ You have to use __HAL_RCC_PLLI2S_CONFIG() macro 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_CONFIG() and __HAL_RCC_RTC_ENABLE()
+ macros to configure this clock.
+ (+@) USB OTG FS, SDIO and RTC: USB OTG FS require a frequency equal to 48 MHz
+ to work correctly, while the SDIO require a frequency equal or lower than
+ to 48. This clock is derived of the main PLL through PLLQ divider.
+ (+@) IWDG clock which is always the LSI clock.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Resets the RCC clock configuration to the default reset state.
+ * @note The default reset state of the clock configuration is given below:
+ * - HSI ON and used as system clock source
+ * - HSE, PLL and PLLI2S OFF
+ * - AHB, APB1 and APB2 prescaler set to 1.
+ * - CSS, MCO1 and MCO2 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 HSION bit */
+ SET_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSITRIM_4);
+
+ /* Reset CFGR register */
+ CLEAR_REG(RCC->CFGR);
+
+ /* Reset HSEON, CSSON, PLLON, PLLI2S */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_CSSON | RCC_CR_PLLON| RCC_CR_PLLI2SON);
+
+ /* Reset PLLCFGR register */
+ CLEAR_REG(RCC->PLLCFGR);
+ SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2);
+
+ /* Reset PLLI2SCFGR register */
+ CLEAR_REG(RCC->PLLI2SCFGR);
+ SET_BIT(RCC->PLLI2SCFGR, RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1);
+
+ /* Reset HSEBYP bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
+
+ /* Disable all interrupts */
+ CLEAR_REG(RCC->CIR);
+}
+
+/**
+ * @brief Initializes 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(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
+
+ /*------------------------------- 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, It can not be disabled */
+ if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSE)
+ || ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
+ {
+ if((__HAL_RCC_GET_FLAG(RCC_FLAG_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(__HAL_RCC_GET_FLAG(RCC_FLAG_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(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is bypassed or disabled */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_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_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_SYSCLKSOURCE_STATUS_HSI)
+ || ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)))
+ {
+ /* When HSI is used as system clock it will not disabled */
+ if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON))
+ {
+ 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(__HAL_RCC_GET_FLAG(RCC_FLAG_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 ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_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(__HAL_RCC_GET_FLAG(RCC_FLAG_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 ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ /*------------------------------ LSE Configuration -------------------------*/
+ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
+
+ /* Enable Power Clock*/
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* Enable write access to Backup domain */
+ 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)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Reset LSEON and LSEBYP bits before configuring the LSE ----------------*/
+ __HAL_RCC_LSE_CONFIG(RCC_LSE_OFF);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RCC_LSE_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(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ /*-------------------------------- 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_SYSCLKSOURCE_STATUS_PLLCLK)
+ {
+ 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));
+
+ /* Disable the main PLL. */
+ __HAL_RCC_PLL_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_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);
+ /* Enable the main PLL. */
+ __HAL_RCC_PLL_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Disable the main PLL. */
+ __HAL_RCC_PLL_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes 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 depend on device selected
+ *
+ * @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 HSI is used (enabled by hardware) as system clock source after
+ * startup from Reset, wake-up from STOP and STANDBY mode, 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 will be ready.
+ * 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(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 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(__HAL_RCC_GET_FLAG(RCC_FLAG_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(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* HSI is selected as System Clock Source */
+ else
+ {
+ /* Check the HSI ready flag */
+ if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ __HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
+ {
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_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_SYSCLKSOURCE_STATUS_PLLCLK)
+ {
+ if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_HSI)
+ {
+ if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ /* Decreasing the CPU frequency */
+ else
+ {
+ /*-------------------------- 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(__HAL_RCC_GET_FLAG(RCC_FLAG_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(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* HSI is selected as System Clock Source */
+ else
+ {
+ /* Check the HSI ready flag */
+ if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
+ {
+ return HAL_ERROR;
+ }
+ }
+ __HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
+ {
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_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_SYSCLKSOURCE_STATUS_PLLCLK)
+ {
+ if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_HSI)
+ {
+ if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* 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) << 3));
+ }
+
+ /* 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 control the RCC Clocks
+ frequencies.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Selects the clock source to output on MCO1 pin(PA8) or on MCO2 pin(PC9).
+ * @note PA8/PC9 should be configured in alternate function mode.
+ * @param RCC_MCOx: specifies the output direction for the clock source.
+ * This parameter can be one of the following values:
+ * @arg RCC_MCO1: Clock source to output on MCO1 pin(PA8).
+ * @arg RCC_MCO2: Clock source to output on MCO2 pin(PC9).
+ * @param RCC_MCOSource: specifies the clock source to output.
+ * This parameter can be one of the following values:
+ * @arg RCC_MCO1SOURCE_HSI: HSI clock selected as MCO1 source
+ * @arg RCC_MCO1SOURCE_LSE: LSE clock selected as MCO1 source
+ * @arg RCC_MCO1SOURCE_HSE: HSE clock selected as MCO1 source
+ * @arg RCC_MCO1SOURCE_PLLCLK: main PLL clock selected as MCO1 source
+ * @arg RCC_MCO2SOURCE_SYSCLK: System clock (SYSCLK) selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_PLLI2SCLK: PLLI2S clock selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_HSE: HSE clock selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_PLLCLK: main PLL clock selected as MCO2 source
+ * @param RCC_MCODiv: specifies the MCOx prescaler.
+ * This parameter can be one of the following values:
+ * @arg RCC_MCODIV_1: no division applied to MCOx clock
+ * @arg RCC_MCODIV_2: division by 2 applied to MCOx clock
+ * @arg RCC_MCODIV_3: division by 3 applied to MCOx clock
+ * @arg RCC_MCODIV_4: division by 4 applied to MCOx clock
+ * @arg RCC_MCODIV_5: division by 5 applied to MCOx 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));
+ /* RCC_MCO1 */
+ if(RCC_MCOx == RCC_MCO1)
+ {
+ assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
+
+ /* MCO1 Clock Enable */
+ MCO1_CLK_ENABLE();
+
+ /* Configure the MCO1 pin in alternate function mode */
+ GPIO_InitStruct.Pin = MCO1_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
+ HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
+
+ /* Mask MCO1 and MCO1PRE[2:0] bits then Select MCO1 clock source and prescaler */
+ MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCO1 | RCC_CFGR_MCO1PRE), (RCC_MCOSource | RCC_MCODiv));
+ }
+ else
+ {
+ assert_param(IS_RCC_MCO2SOURCE(RCC_MCOSource));
+
+ /* MCO2 Clock Enable */
+ MCO2_CLK_ENABLE();
+
+ /* Configure the MCO2 pin in alternate function mode */
+ GPIO_InitStruct.Pin = MCO2_PIN;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
+ HAL_GPIO_Init(MCO2_GPIO_PORT, &GPIO_InitStruct);
+
+ /* Mask MCO2 and MCO2PRE[2:0] bits then Select MCO2 clock source and prescaler */
+ MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCO2 | RCC_CFGR_MCO2PRE), (RCC_MCOSource | (RCC_MCODiv << 3)));
+ }
+}
+
+/**
+ * @brief Enables 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-M7 NMI (Non-Maskable Interrupt) exception vector.
+ * @retval None
+ */
+void HAL_RCC_EnableCSS(void)
+{
+ SET_BIT(RCC->CR, RCC_CR_CSSON);
+}
+
+/**
+ * @brief Disables the Clock Security System.
+ * @retval None
+ */
+void HAL_RCC_DisableCSS(void)
+{
+ CLEAR_BIT(RCC->CR, RCC_CR_CSSON);
+}
+
+/**
+ * @brief Returns 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 HSI, function returns values based on HSI_VALUE(*)
+ * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
+ * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**)
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.
+ * @note (*) HSI_VALUE is a constant defined in stm32f7xx_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 stm32f7xx_hal_conf.h file (default value
+ * 25 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 pllm = 0, pllvco = 0, pllp = 0;
+ uint32_t sysclockfreq = 0;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ switch (RCC->CFGR & RCC_CFGR_SWS)
+ {
+ case RCC_SYSCLKSOURCE_STATUS_HSI: /* HSI used as system clock source */
+ {
+ sysclockfreq = HSI_VALUE;
+ break;
+ }
+ case RCC_SYSCLKSOURCE_STATUS_HSE: /* HSE used as system clock source */
+ {
+ sysclockfreq = HSE_VALUE;
+ break;
+ }
+ case RCC_SYSCLKSOURCE_STATUS_PLLCLK: /* PLL used as system clock source */
+ {
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
+ SYSCLK = PLL_VCO / PLLP */
+ pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+ if (__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLCFGR_PLLSRC_HSI)
+ {
+ /* HSE used as PLL clock source */
+ pllvco = ((HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN)));
+ }
+ else
+ {
+ /* HSI used as PLL clock source */
+ pllvco = ((HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN)));
+ }
+ pllp = ((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> POSITION_VAL(RCC_PLLCFGR_PLLP)) + 1 ) *2);
+
+ sysclockfreq = pllvco/pllp;
+ break;
+ }
+ default:
+ {
+ sysclockfreq = HSI_VALUE;
+ break;
+ }
+ }
+ return sysclockfreq;
+}
+
+/**
+ * @brief Returns 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
+ * and updated within this function
+ * @retval HCLK frequency
+ */
+uint32_t HAL_RCC_GetHCLKFreq(void)
+{
+ SystemCoreClock = HAL_RCC_GetSysClockFreq() >> APBAHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> POSITION_VAL(RCC_CFGR_HPRE)];
+ return SystemCoreClock;
+}
+
+/**
+ * @brief Returns 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
+ */
+uint32_t HAL_RCC_GetPCLK1Freq(void)
+{
+ /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> APBAHBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1)>> POSITION_VAL(RCC_CFGR_PPRE1)]);
+}
+
+/**
+ * @brief Returns 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
+ */
+uint32_t HAL_RCC_GetPCLK2Freq(void)
+{
+ /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq()>> APBAHBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2)>> POSITION_VAL(RCC_CFGR_PPRE2)]);
+}
+
+/**
+ * @brief Configures 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)
+{
+ /* Set all possible values for the Oscillator type parameter ---------------*/
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | 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 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->CR &RCC_CR_HSITRIM) >> POSITION_VAL(RCC_CR_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);
+ RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> POSITION_VAL(RCC_PLLCFGR_PLLN));
+ RCC_OscInitStruct->PLL.PLLP = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) + RCC_PLLCFGR_PLLP_0) << 1) >> POSITION_VAL(RCC_PLLCFGR_PLLP));
+ RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> POSITION_VAL(RCC_PLLCFGR_PLLQ));
+}
+
+/**
+ * @brief Configures 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)
+{
+ /* 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) >> 3);
+
+ /* Get the Flash Wait State (Latency) configuration ------------------------*/
+ *pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_LATENCY);
+}
+
+/**
+ * @brief This function handles the RCC CSS interrupt request.
+ * @note This API should be called under the NMI_Handler().
+ * @retval None
+ */
+void HAL_RCC_NMI_IRQHandler(void)
+{
+ /* Check RCC CSSF 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 could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_rcc_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_rcc_ex.c
new file mode 100644
index 0000000000..e04960d33e
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_rcc_ex.c
@@ -0,0 +1,861 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_rcc_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief Extension RCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities RCC extension peripheral:
+ * + Extended Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RCCEx RCCEx
+ * @brief RCCEx HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup RCCEx_Private_Defines RCCEx Private Defines
+ * @{
+ */
+
+#define PLLI2S_TIMEOUT_VALUE 100 /* Timeout value fixed to 100 ms */
+#define PLLSAI_TIMEOUT_VALUE 100 /* Timeout value fixed to 100 ms */
+
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup RCCEx_Private_Macros RCCEx Private Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup RCCEx_Private_Macros RCCEx Private Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private 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 will be set to their reset values.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the RCC extended peripherals clocks according to the specified
+ * parameters in the RCC_PeriphCLKInitTypeDef.
+ * @param PeriphClkInit: pointer to an RCC_PeriphCLKInitTypeDef structure that
+ * contains the configuration information for the Extended Peripherals
+ * clocks(I2S, SAI, LTDC RTC, TIM, UARTs, USARTs, LTPIM, SDMMC...).
+ *
+ * @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.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ uint32_t tickstart = 0;
+ uint32_t tmpreg0 = 0;
+ uint32_t tmpreg1 = 0;
+ uint32_t plli2sused = 0;
+ uint32_t pllsaiused = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
+
+ /*----------------------------------- I2S configuration ----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2SCLKSOURCE(PeriphClkInit->I2sClockSelection));
+
+ /* Configure I2S Clock source */
+ __HAL_RCC_I2S_CONFIG(PeriphClkInit->I2sClockSelection);
+
+ /* Enable the PLLI2S when it's used as clock source for I2S */
+ if(PeriphClkInit->I2sClockSelection == RCC_I2SCLKSOURCE_PLLI2S)
+ {
+ plli2sused = 1;
+ }
+ }
+
+ /*------------------------------------ SAI1 configuration --------------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == (RCC_PERIPHCLK_SAI1))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SAI1CLKSOURCE(PeriphClkInit->Sai1ClockSelection));
+
+ /* Configure SAI1 Clock source */
+ __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
+ /* Enable the PLLI2S when it's used as clock source for SAI */
+ if(PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)
+ {
+ plli2sused = 1;
+ }
+ /* Enable the PLLSAI when it's used as clock source for SAI */
+ if(PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)
+ {
+ pllsaiused = 1;
+ }
+ }
+
+ /*------------------------------------ SAI2 configuration --------------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == (RCC_PERIPHCLK_SAI2))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SAI2CLKSOURCE(PeriphClkInit->Sai2ClockSelection));
+
+ /* Configure SAI2 Clock source */
+ __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection);
+
+ /* Enable the PLLI2S when it's used as clock source for SAI */
+ if(PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S)
+ {
+ plli2sused = 1;
+ }
+ /* Enable the PLLSAI when it's used as clock source for SAI */
+ if(PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI)
+ {
+ pllsaiused = 1;
+ }
+ }
+
+ /*-------------------------------------- SPDIF-RX Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX)
+ {
+ plli2sused = 1;
+ }
+
+ /*------------------------------------ RTC configuration --------------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
+ {
+ /* Reset the Backup domain only if the RTC Clock source selection is modified */
+ if((RCC->BDCR & RCC_BDCR_RTCSEL) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))
+ {
+ /* Enable Power Clock*/
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* Enable write access to Backup domain */
+ PWR->CR1 |= PWR_CR1_DBP;
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait for Backup domain Write protection disable */
+ while((PWR->CR1 & PWR_CR1_DBP) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Store the content of BDCR register before the reset of Backup Domain */
+ tmpreg0 = (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 = tmpreg0;
+
+ /* If LSE is selected as RTC clock source, wait for LSE reactivation */
+ if (HAL_IS_BIT_SET(tmpreg0, RCC_BDCR_LSERDY))
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
+ }
+ }
+
+ /*------------------------------------ TIM configuration --------------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_TIMPRES(PeriphClkInit->TIMPresSelection));
+
+ /* Configure Timer Prescaler */
+ __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
+ }
+
+ /*-------------------------------------- I2C1 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 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 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);
+ }
+
+ /*-------------------------------------- I2C4 Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C4CLKSOURCE(PeriphClkInit->I2c4ClockSelection));
+
+ /* Configure the I2C4 clock source */
+ __HAL_RCC_I2C4_CONFIG(PeriphClkInit->I2c4ClockSelection);
+ }
+
+ /*-------------------------------------- USART1 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 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 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 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 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);
+ }
+
+ /*-------------------------------------- USART6 Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART6) == RCC_PERIPHCLK_USART6)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_USART6CLKSOURCE(PeriphClkInit->Usart6ClockSelection));
+
+ /* Configure the USART6 clock source */
+ __HAL_RCC_USART6_CONFIG(PeriphClkInit->Usart6ClockSelection);
+ }
+
+ /*-------------------------------------- UART7 Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART7) == RCC_PERIPHCLK_UART7)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_UART7CLKSOURCE(PeriphClkInit->Uart7ClockSelection));
+
+ /* Configure the UART7 clock source */
+ __HAL_RCC_UART7_CONFIG(PeriphClkInit->Uart7ClockSelection);
+ }
+
+ /*-------------------------------------- UART8 Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART8) == RCC_PERIPHCLK_UART8)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_UART8CLKSOURCE(PeriphClkInit->Uart8ClockSelection));
+
+ /* Configure the UART8 clock source */
+ __HAL_RCC_UART8_CONFIG(PeriphClkInit->Uart8ClockSelection);
+ }
+
+ /*--------------------------------------- CEC Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CEC) == RCC_PERIPHCLK_CEC)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_CECCLKSOURCE(PeriphClkInit->CecClockSelection));
+
+ /* Configure the CEC clock source */
+ __HAL_RCC_CEC_CONFIG(PeriphClkInit->CecClockSelection);
+ }
+
+ /*-------------------------------------- CK48 Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_CLK48SOURCE(PeriphClkInit->Clk48ClockSelection));
+
+ /* Configure the CLK48 source */
+ __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);
+
+ /* Enable the PLLSAI when it's used as clock source for CK48 */
+ if(PeriphClkInit->Clk48ClockSelection == RCC_CLK48SOURCE_PLLSAIP)
+ {
+ pllsaiused = 1;
+ }
+ }
+
+ /*-------------------------------------- LTDC Configuration -----------------------------------*/
+#if defined(STM32F756xx) || defined(STM32F746xx)
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)
+ {
+ pllsaiused = 1;
+ }
+#endif /* STM32F756xx || STM32F746xx */
+ /*-------------------------------------- LPTIM1 Configuration -----------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection));
+
+ /* Configure the LTPIM1 clock source */
+ __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
+ }
+
+ /*------------------------------------- SDMMC Configuration ------------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection));
+
+ /* Configure the SDMMC1 clock source */
+ __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection);
+ }
+
+ /*-------------------------------------- PLLI2S Configuration ---------------------------------*/
+ /* PLLI2S is configured when a peripheral will use it as source clock : SAI1, SAI2, I2S or SPDIF-RX */
+ if((plli2sused == 1) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
+ {
+ /* Disable the PLLI2S */
+ __HAL_RCC_PLLI2S_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLI2S is disabled */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
+ {
+ /* return in case of Timeout detected */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* check for common PLLI2S Parameters */
+ assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
+
+ /*----------------- In Case of PLLI2S is selected as source clock for I2S -------------------*/
+ if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) && (PeriphClkInit->I2sClockSelection == RCC_I2SCLKSOURCE_PLLI2S)))
+ {
+ /* check for Parameters */
+ assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
+
+ /* Read PLLI2SP and PLLI2SQ value from PLLI2SCFGR register (this value is not needed for I2S configuration) */
+ tmpreg0 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP));
+ tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ));
+ /* Configure the PLLI2S division factors */
+ /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x (PLLI2SN/PLLM) */
+ /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
+ __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , tmpreg0, tmpreg1, PeriphClkInit->PLLI2S.PLLI2SR);
+ }
+
+ /*----------------- In Case of PLLI2S is selected as source clock for SAI -------------------*/
+ if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)) ||
+ ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S)))
+ {
+ /* Check for PLLI2S Parameters */
+ assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
+ /* Check for PLLI2S/DIVQ parameters */
+ assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));
+
+ /* Read PLLI2SP and PLLI2SR values from PLLI2SCFGR register (this value is not needed for SAI configuration) */
+ tmpreg0 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP));
+ tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR));
+ /* Configure the PLLI2S division factors */
+ /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */
+ /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
+ /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
+ __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, tmpreg0, PeriphClkInit->PLLI2S.PLLI2SQ, tmpreg1);
+
+ /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
+ __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
+ }
+
+ /*----------------- In Case of PLLI2S is selected as source clock for SPDIF-RX -------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX)
+ {
+ /* check for Parameters */
+ assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP));
+
+ /* Read PLLI2SR value from PLLI2SCFGR register (this value is not needed for SPDIF-RX configuration) */
+ tmpreg0 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ));
+ tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR));
+ /* Configure the PLLI2S division factors */
+ /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x (PLLI2SN/PLLM) */
+ /* SPDIFCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */
+ __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SP, tmpreg0, tmpreg1);
+ }
+
+ /*----------------- In Case of PLLI2S is just selected -----------------*/
+ if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
+ {
+ /* Check for Parameters */
+ assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
+ assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP));
+ assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
+ assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
+
+ /* Configure the PLLI2S division factors */
+ /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x (PLLI2SN/PLLI2SM) */
+ /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */
+ __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SP, PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
+ }
+
+ /* Enable the PLLI2S */
+ __HAL_RCC_PLLI2S_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLI2S is ready */
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
+ {
+ /* return in case of Timeout detected */
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /*-------------------------------------- PLLSAI Configuration ---------------------------------*/
+ /* PLLSAI is configured when a peripheral will use it as source clock : SAI1, SAI2, LTDC or CK48 */
+ if(pllsaiused == 1)
+ {
+ /* Disable PLLSAI Clock */
+ __HAL_RCC_PLLSAI_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI is disabled */
+ while(__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
+ {
+ /* return in case of Timeout detected */
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check the PLLSAI division factors */
+ assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));
+
+ /*----------------- In Case of PLLSAI is selected as source clock for SAI -------------------*/
+ if(((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)) ||
+ ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI)))
+ {
+ /* check for PLLSAIQ Parameter */
+ assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
+ /* check for PLLSAI/DIVQ Parameter */
+ assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));
+
+ /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
+ tmpreg0 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP));
+ tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR));
+ /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */
+ /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
+ /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
+ __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN , tmpreg0, PeriphClkInit->PLLSAI.PLLSAIQ, tmpreg1);
+
+ /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
+ __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
+ }
+
+ /*----------------- In Case of PLLSAI is selected as source clock for CLK48 -------------------*/
+ /* In Case of PLLI2S is selected as source clock for CK48 */
+ if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48SOURCE_PLLSAIP))
+ {
+ /* check for Parameters */
+ assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP));
+ /* Read PLLSAIQ and PLLSAIR value from PLLSAICFGR register (this value is not needed for CK48 configuration) */
+ tmpreg0 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ));
+ tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR));
+
+ /* Configure the PLLSAI division factors */
+ /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) x (PLLI2SN/PLLM) */
+ /* 48CLK = f(PLLSAI clock output) = f(VCO clock) / PLLSAIP */
+ __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN , PeriphClkInit->PLLSAI.PLLSAIP, tmpreg0, tmpreg1);
+ }
+
+#if defined(STM32F756xx) || defined(STM32F746xx)
+ /*---------------------------- LTDC configuration -------------------------------*/
+ if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC))
+ {
+ assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR));
+ assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR));
+
+ /* Read PLLSAIP and PLLSAIQ value from PLLSAICFGR register (these value are not needed for LTDC configuration) */
+ tmpreg0 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ));
+ tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP));
+
+ /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */
+ /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
+ /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */
+ __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN , tmpreg1, tmpreg0, PeriphClkInit->PLLSAI.PLLSAIR);
+
+ /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */
+ __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR);
+ }
+#endif /* STM32F756xx || STM32F746xx */
+
+ /* Enable PLLSAI Clock */
+ __HAL_RCC_PLLSAI_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLLSAI is ready */
+ while(__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
+ {
+ if((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
+ {
+ /* return in case of Timeout detected */
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the RCC_PeriphCLKInitTypeDef according to the internal
+ * RCC configuration registers.
+ * @param PeriphClkInit: pointer to the configured RCC_PeriphCLKInitTypeDef structure
+ * @retval None
+ */
+void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ uint32_t tempreg = 0;
+
+ /* Set all possible values for the extended clock type parameter------------*/
+ PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_LPTIM1 |\
+ RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 |\
+ RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC |\
+ RCC_PERIPHCLK_CEC | RCC_PERIPHCLK_I2C4 |\
+ RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 |\
+ RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_USART1 |\
+ RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 |\
+ RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 |\
+ RCC_PERIPHCLK_USART6 | RCC_PERIPHCLK_UART7 |\
+ RCC_PERIPHCLK_UART8 | RCC_PERIPHCLK_SDMMC1 |\
+ RCC_PERIPHCLK_CLK48;
+
+ /* Get the PLLI2S Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SN));
+ PeriphClkInit->PLLI2S.PLLI2SP = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SP));
+ PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SQ));
+ PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> POSITION_VAL(RCC_PLLI2SCFGR_PLLI2SR));
+
+ /* Get the PLLSAI Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIN));
+ PeriphClkInit->PLLSAI.PLLSAIP = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIP));
+ PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIQ));
+ PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> POSITION_VAL(RCC_PLLSAICFGR_PLLSAIR));
+
+ /* Get the PLLSAI/PLLI2S division factors -------------------------------------------*/
+ PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR1 & RCC_DCKCFGR1_PLLI2SDIVQ) >> POSITION_VAL(RCC_DCKCFGR1_PLLI2SDIVQ));
+ PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR1 & RCC_DCKCFGR1_PLLSAIDIVQ) >> POSITION_VAL(RCC_DCKCFGR1_PLLSAIDIVQ));
+ PeriphClkInit->PLLSAIDivR = (uint32_t)((RCC->DCKCFGR1 & RCC_DCKCFGR1_PLLSAIDIVR) >> POSITION_VAL(RCC_DCKCFGR1_PLLSAIDIVR));
+
+ /* Get the SAI1 clock configuration ----------------------------------------------*/
+ PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();
+
+ /* Get the SAI2 clock configuration ----------------------------------------------*/
+ PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE();
+
+ /* Get the I2S clock configuration ------------------------------------------*/
+ PeriphClkInit->I2sClockSelection = __HAL_RCC_GET_I2SCLKSOURCE();
+
+ /* Get the I2C1 clock configuration ------------------------------------------*/
+ PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
+
+ /* Get the I2C2 clock configuration ------------------------------------------*/
+ PeriphClkInit->I2c2ClockSelection = __HAL_RCC_GET_I2C2_SOURCE();
+
+ /* Get the I2C3 clock configuration ------------------------------------------*/
+ PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE();
+
+ /* Get the I2C4 clock configuration ------------------------------------------*/
+ PeriphClkInit->I2c4ClockSelection = __HAL_RCC_GET_I2C4_SOURCE();
+
+ /* Get the USART1 clock configuration ------------------------------------------*/
+ PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
+
+ /* Get the USART2 clock configuration ------------------------------------------*/
+ PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE();
+
+ /* Get the USART3 clock configuration ------------------------------------------*/
+ PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE();
+
+ /* Get the UART4 clock configuration ------------------------------------------*/
+ PeriphClkInit->Uart4ClockSelection = __HAL_RCC_GET_UART4_SOURCE();
+
+ /* Get the UART5 clock configuration ------------------------------------------*/
+ PeriphClkInit->Uart5ClockSelection = __HAL_RCC_GET_UART5_SOURCE();
+
+ /* Get the USART6 clock configuration ------------------------------------------*/
+ PeriphClkInit->Usart6ClockSelection = __HAL_RCC_GET_USART6_SOURCE();
+
+ /* Get the UART7 clock configuration ------------------------------------------*/
+ PeriphClkInit->Uart7ClockSelection = __HAL_RCC_GET_UART7_SOURCE();
+
+ /* Get the UART8 clock configuration ------------------------------------------*/
+ PeriphClkInit->Uart8ClockSelection = __HAL_RCC_GET_UART8_SOURCE();
+
+ /* Get the LPTIM1 clock configuration ------------------------------------------*/
+ PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
+
+ /* Get the CEC clock configuration -----------------------------------------------*/
+ PeriphClkInit->CecClockSelection = __HAL_RCC_GET_CEC_SOURCE();
+
+ /* Get the CK48 clock configuration -----------------------------------------------*/
+ PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();
+
+ /* Get the SDMMC clock configuration -----------------------------------------------*/
+ PeriphClkInit->Sdmmc1ClockSelection = __HAL_RCC_GET_SDMMC1_SOURCE();
+
+ /* Get the RTC Clock configuration -----------------------------------------------*/
+ tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
+ PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
+
+ /* Get the TIM Prescaler configuration --------------------------------------------*/
+ if ((RCC->DCKCFGR1 & RCC_DCKCFGR1_TIMPRE) == RESET)
+ {
+ PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
+ }
+ else
+ {
+ PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
+ }
+}
+
+/**
+ * @brief Return the peripheral clock frequency for a given peripheral(SAI..)
+ * @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 RCC_PERIPHCLK_SAI1: SAI1 peripheral clock
+ * @arg RCC_PERIPHCLK_SAI2: SAI2 peripheral clock
+ * @retval Frequency in KHz
+ */
+uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
+{
+ uint32_t tmpreg = 0;
+ /* This variable used to store the SAI clock frequency (value in Hz) */
+ uint32_t frequency = 0;
+ /* This variable used to store the VCO Input (value in Hz) */
+ uint32_t vcoinput = 0;
+ /* This variable used to store the SAI clock source */
+ uint32_t saiclocksource = 0;
+ if ((PeriphClk == RCC_PERIPHCLK_SAI1) || (PeriphClk == RCC_PERIPHCLK_SAI2))
+ {
+ saiclocksource = RCC->DCKCFGR1;
+ saiclocksource &= (RCC_DCKCFGR1_SAI1SEL | RCC_DCKCFGR1_SAI2SEL);
+ switch (saiclocksource)
+ {
+ case 0: /* PLLSAI is the clock source for SAI*/
+ {
+ /* Configure the PLLSAI division factor */
+ /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */
+ if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
+ {
+ /* In Case the PLL Source is HSI (Internal Clock) */
+ vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
+ }
+ else
+ {
+ /* In Case the PLL Source is HSE (External Clock) */
+ vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)));
+ }
+ /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
+ /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
+ tmpreg = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24;
+ frequency = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6))/(tmpreg);
+
+ /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
+ tmpreg = (((RCC->DCKCFGR1 & RCC_DCKCFGR1_PLLSAIDIVQ) >> 8) + 1);
+ frequency = frequency/(tmpreg);
+ break;
+ }
+ case RCC_DCKCFGR1_SAI1SEL_0: /* PLLI2S is the clock source for SAI*/
+ case RCC_DCKCFGR1_SAI2SEL_0: /* PLLI2S is the clock source for SAI*/
+ {
+ /* Configure the PLLI2S division factor */
+ /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */
+ if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
+ {
+ /* In Case the PLL Source is HSI (Internal Clock) */
+ vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
+ }
+ else
+ {
+ /* In Case the PLL Source is HSE (External Clock) */
+ vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)));
+ }
+
+ /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
+ /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
+ tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24;
+ frequency = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6))/(tmpreg);
+
+ /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
+ tmpreg = ((RCC->DCKCFGR1 & RCC_DCKCFGR1_PLLI2SDIVQ) + 1);
+ frequency = frequency/(tmpreg);
+ break;
+ }
+ case RCC_DCKCFGR1_SAI1SEL_1: /* External clock is the clock source for SAI*/
+ case RCC_DCKCFGR1_SAI2SEL_1: /* External clock is the clock source for SAI*/
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+ default :
+ {
+ break;
+ }
+ }
+ }
+ return frequency;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_rng.c b/stmhal/hal/f7/src/stm32f7xx_hal_rng.c
new file mode 100644
index 0000000000..e4b3d20380
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_rng.c
@@ -0,0 +1,510 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_rng.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup RNG
+ * @{
+ */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup RNG_Private_Constants
+ * @{
+ */
+#define RNG_TIMEOUT_VALUE 2
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/* Private functions 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
+ (+) DeInitialize RNG MSP
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the RNG peripheral and creates the associated handle.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng)
+{
+ /* Check the RNG handle allocation */
+ if(hrng == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ __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 DeInitializes the RNG peripheral.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @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 Initializes the RNG MSP.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+ */
+__weak void HAL_RNG_MspInit(RNG_HandleTypeDef *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 DeInitializes the RNG MSP.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+ */
+__weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *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 Peripheral Control 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 Generates 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 that contains
+ * the configuration information for RNG.
+ * @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 RNG 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 Generates a 32-bit random number in interrupt mode.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @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 Handles 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 that contains
+ * the configuration information for RNG.
+ * @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 Returns generated random number in polling mode (Obsolete)
+ * 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 Returns a 32-bit random number with interrupt enabled (Obsolete),
+ * Use HAL_RNG_GenerateRandomNumber_IT() API instead.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @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 that contains
+ * the configuration information for RNG.
+ * @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 that contains
+ * the configuration information for RNG.
+ * @param random32bit: generated random number.
+ * @retval None
+ */
+__weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t 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 callbacks.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval None
+ */
+__weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *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
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the RNG state.
+ * @param hrng: pointer to a RNG_HandleTypeDef structure that contains
+ * the configuration information for RNG.
+ * @retval HAL state
+ */
+HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng)
+{
+ return hrng->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_rtc.c b/stmhal/hal/f7/src/stm32f7xx_hal_rtc.c
new file mode 100644
index 0000000000..83bfcc6589
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_rtc.c
@@ -0,0 +1,1555 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_rtc.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real Time Clock (RTC) peripheral:
+ * + Initialization and de-initialization functions
+ * + RTC Time and Date functions
+ * + RTC Alarm functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### Backup Domain Operating Condition #####
+ ==============================================================================
+ [..] The real-time clock (RTC), the RTC backup registers, and the backup
+ SRAM (BKP SRAM) can be powered from the VBAT voltage when the main
+ VDD supply is powered off.
+ To retain the content of the RTC backup registers, backup SRAM, and supply
+ the RTC when VDD is turned off, VBAT pin can be connected to an optional
+ standby voltage supplied by a battery or by another source.
+
+ [..] To allow the RTC operating even when the main digital supply (VDD) is turned
+ off, the VBAT pin powers the following blocks:
+ (#) The RTC
+ (#) The LSE oscillator
+ (#) The backup SRAM when the low power backup regulator is enabled
+ (#) PC13 to PC15 I/Os, plus PI8 I/O (when available)
+
+ [..] When the backup domain is supplied by VDD (analog switch connected to VDD),
+ the following pins are available:
+ (#) PC14 and PC15 can be used as either GPIO or LSE pins
+ (#) PC13 can be used as a GPIO or as the RTC_AF1 pin
+ (#) PI8 can be used as a GPIO or as the RTC_AF2 pin
+
+ [..] When the backup domain is supplied by VBAT (analog switch connected to VBAT
+ because VDD is not present), the following pins are available:
+ (#) PC14 and PC15 can be used as LSE pins only
+ (#) PC13 can be used as the RTC_AF1 pin
+ (#) PI8 can be used as the RTC_AF2 pin
+ (#) PC1 can be used as the RTC_AF3 pin
+
+ ##### Backup Domain Reset #####
+ ==================================================================
+ [..] The backup domain reset sets all RTC registers and the RCC_BDCR register
+ to their reset values. The BKPSRAM is not affected by this reset. The only
+ way to reset the BKPSRAM is through the Flash interface by requesting
+ a protection level change from 1 to 0.
+ [..] 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.
+
+ ##### 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:
+ (+) Enable the Power Controller (PWR) APB1 interface clock using the
+ __HAL_RCC_PWR_CLK_ENABLE() function.
+ (+) Enable access to RTC domain using the HAL_PWR_EnableBkUpAccess() function.
+ (+) Select the RTC clock source using the __HAL_RCC_RTC_CONFIG() function.
+ (+) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() function.
+
+
+ ##### How to use this driver #####
+ ==================================================================
+ [..]
+ (+) Enable the RTC domain access (see description in the section above).
+ (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour
+ format using the HAL_RTC_Init() function.
+
+ *** Time and Date configuration ***
+ ===================================
+ [..]
+ (+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
+ and HAL_RTC_SetDate() functions.
+ (+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions.
+
+ *** 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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 -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup RTC_Exported_Functions RTC Exported Functions
+ * @{
+ */
+
+/** @defgroup RTC_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to initialize and configure the
+ RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable
+ RTC registers Write protection, enter and exit the RTC initialization mode,
+ RTC registers synchronization check and reference clock detection enable.
+ (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base.
+ It is split into 2 programmable prescalers to minimize power consumption.
+ (++) A 7-bit asynchronous prescaler and a 13-bit synchronous prescaler.
+ (++) When both prescalers are used, it is recommended to configure the
+ asynchronous prescaler to a high value to minimize power consumption.
+ (#) All RTC registers are Write protected. Writing to the RTC registers
+ is enabled by writing a key into the Write Protection register, RTC_WPR.
+ (#) To configure the RTC Calendar, user application should enter
+ initialization mode. In this mode, the calendar counter is stopped
+ and its value can be updated. When the initialization sequence is
+ complete, the calendar restarts counting after 4 RTCCLK cycles.
+ (#) To read the calendar through the shadow registers after Calendar
+ initialization, calendar update or after wakeup from low power modes
+ the software must first clear the RSF flag. The software must then
+ wait until it is set again before reading the calendar, which means
+ that the calendar registers have been correctly copied into the
+ RTC_TR and RTC_DR shadow registers.The HAL_RTC_WaitForSynchro() function
+ implements the above software sequence (RSF clear and RSF check).
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the RTC peripheral
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
+{
+ /* 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_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_ALARMTYPE;
+ hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType);
+
+ /* 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 DeInitializes the RTC peripheral
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @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)0x00002101;
+ /* Reset All CR bits except CR[2:0] */
+ hrtc->Instance->CR &= (uint32_t)0x00000007;
+
+ /* Get tick */
+ 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 = (uint32_t)0x0000FFFF;
+ hrtc->Instance->PRER = (uint32_t)0x007F00FF;
+ 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 and alternate functions 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 Initializes the RTC MSP.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes the RTC MSP.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc)
+{
+ /* 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_Group2 RTC Time and Date functions
+ * @brief RTC Time and Date functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Time and Date functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Time and Date features
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets RTC current time.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTime: Pointer to Time structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg FORMAT_BIN: Binary data format
+ * @arg 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 Gets 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 values from the correspondent registers*/
+ sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR);
+
+ /* 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 Sets RTC current date.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sDate: Pointer to date structure
+ * @param Format: specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
+{
+ uint32_t datetmpreg = 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 Gets RTC current date.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sDate: Pointer to Date structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg RTC_FORMAT_BIN: Binary data format
+ * @arg RTC_FORMAT_BCD: BCD data format
+ * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values
+ * in the higher-order calendar shadow registers to ensure consistency between the time and date values.
+ * Reading RTC current time locks the values in calendar shadow registers until Current date is read.
+ * @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_Group3 RTC Alarm functions
+ * @brief RTC Alarm functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Alarm functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Alarm feature
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Sets the specified RTC Alarm.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sAlarm: Pointer to Alarm structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg FORMAT_BIN: Binary data format
+ * @arg 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);
+
+ /* Get tick */
+ 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);
+
+ /* Get tick */
+ 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 Sets the specified RTC Alarm with Interrupt
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sAlarm: Pointer to Alarm structure
+ * @param Format: Specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * @arg FORMAT_BIN: Binary data format
+ * @arg 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);
+
+ /* Get tick */
+ 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);
+
+ /* Get tick */
+ 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();
+
+ EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT;
+
+ /* 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 Deactive the specified RTC Alarm
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Alarm: Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: 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);
+
+ /* Get tick */
+ 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);
+
+ /* Get tick */
+ 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 Gets the RTC Alarm value and masks.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sAlarm: Pointer to Date structure
+ * @param Alarm: Specifies the Alarm.
+ * This parameter can be one of the following values:
+ * @arg RTC_ALARM_A: 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 */
+ 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 This function handles Alarm interrupt request.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef* hrtc)
+{
+ if(__HAL_RTC_ALARM_GET_IT(hrtc, RTC_IT_ALRA))
+ {
+ /* Get the status of the Interrupt */
+ if((uint32_t)(hrtc->Instance->CR & RTC_IT_ALRA) != (uint32_t)RESET)
+ {
+ /* AlarmA callback */
+ HAL_RTC_AlarmAEventCallback(hrtc);
+
+ /* Clear the Alarm interrupt pending bit */
+ __HAL_RTC_ALARM_CLEAR_FLAG(hrtc,RTC_FLAG_ALRAF);
+ }
+ }
+
+ if(__HAL_RTC_ALARM_GET_IT(hrtc, RTC_IT_ALRB))
+ {
+ /* Get the status of the Interrupt */
+ if((uint32_t)(hrtc->Instance->CR & RTC_IT_ALRB) != (uint32_t)RESET)
+ {
+ /* AlarmB callback */
+ HAL_RTCEx_AlarmBEventCallback(hrtc);
+
+ /* Clear the Alarm 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: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *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 This function handles AlarmA Polling request.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ 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_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 Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are
+ * synchronized with RTC APB clock.
+ * @note The RTC Resynchronization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @note To read the calendar through the shadow registers after Calendar
+ * initialization, calendar update or after wakeup from low power modes
+ * the software must first clear the RSF flag.
+ * The software must then wait until it is set again before reading
+ * the calendar, which means that the calendar registers have been
+ * correctly copied into the RTC_TR and RTC_DR shadow registers.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc)
+{
+ uint32_t tickstart = 0;
+
+ /* Clear RSF flag */
+ hrtc->Instance->ISR &= (uint32_t)RTC_RSF_MASK;
+
+ /* Get tick */
+ 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_Group5 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Get RTC state
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Returns the RTC state.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL state
+ */
+HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef* hrtc)
+{
+ return hrtc->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Enters the RTC Initialization mode.
+ * @note The RTC Initialization mode is write protected, use the
+ * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc)
+{
+ uint32_t tickstart = 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;
+
+ /* Get tick */
+ 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 Converts 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 Converts 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/f7/src/stm32f7xx_hal_rtc_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_rtc_ex.c
new file mode 100644
index 0000000000..c541b7b29d
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_rtc_ex.c
@@ -0,0 +1,1813 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_rtc_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief RTC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Real Time Clock (RTC) Extension peripheral:
+ * + RTC Time Stamp functions
+ * + RTC Tamper functions
+ * + RTC Wake-up functions
+ * + Extension Control functions
+ * + Extension 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_RTC_SetWakeUpTimer()
+ function. You can also configure the RTC Wakeup timer in interrupt mode
+ using the HAL_RTC_SetWakeUpTimer_IT() function.
+ (+) To read the RTC WakeUp Counter register, use the HAL_RTC_GetWakeUpTimer()
+ function.
+
+ *** TimeStamp configuration ***
+ ===============================
+ [..]
+ (+) Enables the RTC TimeStamp using the HAL_RTC_SetTimeStamp() function.
+ You can also configure the RTC TimeStamp with interrupt mode using the
+ HAL_RTC_SetTimeStamp_IT() function.
+ (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTC_GetTimeStamp()
+ function.
+
+ *** Internal TimeStamp configuration ***
+ ===============================
+ [..]
+ (+) Enables the RTC internal TimeStamp using the HAL_RTC_SetInternalTimeStamp() function.
+ (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTC_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_RTC_SetTamper() function. You can configure RTC Tamper
+ with interrupt mode using HAL_RTC_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_RTC_BKUPWrite()
+ function.
+ (+) To read the RTC Backup Data registers, use the HAL_RTC_BKUPRead()
+ function.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RTCEx RTCEx
+ * @brief RTC Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions
+ * @{
+ */
+
+
+/** @defgroup RTCEx_Group1 RTC TimeStamp and Tamper functions
+ * @brief RTC TimeStamp and Tamper functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC TimeStamp and Tamper functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure TimeStamp feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets TimeStamp.
+ * @note This API must be called before enabling the TimeStamp feature.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param 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_PC13: PC13 is selected as RTC TimeStamp Pin.
+ * @arg RTC_TIMESTAMPPIN_PI8: PI8 is selected as RTC TimeStamp Pin.
+ * @arg RTC_TIMESTAMPPIN_PC1: PC1 is selected as RTC TimeStamp Pin.
+ * @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);
+
+ hrtc->Instance->OR &= (uint32_t)~RTC_OR_TSINSEL;
+ hrtc->Instance->OR |= (uint32_t)(RTC_TimeStampPin);
+
+ /* 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 Sets TimeStamp with Interrupt.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note This API must be called before enabling the TimeStamp feature.
+ * @param 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_PC13: PC13 is selected as RTC TimeStamp Pin.
+ * @arg RTC_TIMESTAMPPIN_PI8: PI8 is selected as RTC TimeStamp Pin.
+ * @arg RTC_TIMESTAMPPIN_PC1: PC1 is selected as RTC TimeStamp Pin.
+ * @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;
+
+ hrtc->Instance->OR &= (uint32_t)~RTC_OR_TSINSEL;
+ hrtc->Instance->OR |= (uint32_t)(RTC_TimeStampPin);
+
+ __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();
+
+ EXTI->RTSR |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT;
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates TimeStamp.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ uint32_t tmpreg = 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 Sets Internal TimeStamp.
+ * @note This API must be called before enabling the internal TimeStamp feature.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* 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 Deactivates internal TimeStamp.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Configure the internal 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 Gets the RTC TimeStamp value.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTimeStamp: Pointer to Time structure
+ * @param sTimeStampDate: Pointer to Date structure
+ * @param Format: specifies the format of the entered parameters.
+ * This parameter can be one of the following values:
+ * FORMAT_BIN: Binary data format
+ * 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 Flag */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets Tamper
+ * @note By calling this API we disable the tamper interrupt for all tampers.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTamper: Pointer to Tamper Structure.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper)
+{
+ uint32_t tmpreg = 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;
+
+ 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((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE;
+ }
+ }
+
+ if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ sTamper->MaskFlag = 0;
+ if((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF;
+ }
+ }
+
+ 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) | (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_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE |\
+ (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\
+ (uint32_t)RTC_TAMPCR_TAMP2MF | (uint32_t)RTC_TAMPCR_TAMP3MF);
+
+ hrtc->Instance->TAMPCR |= tmpreg;
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets Tamper with interrupt.
+ * @note By calling this API we force the tamper interrupt for all tampers.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param sTamper: Pointer to RTC Tamper.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper)
+{
+ uint32_t tmpreg = 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((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE;
+ }
+ }
+
+ if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE)
+ {
+ sTamper->MaskFlag = 0;
+ if((sTamper->Tamper & RTC_TAMPER_1) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_2) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF;
+ }
+ if((sTamper->Tamper & RTC_TAMPER_3) != 0)
+ {
+ sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF;
+ }
+ }
+
+ 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) | (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_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE |\
+ (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\
+ (uint32_t)RTC_TAMPCR_TAMP2MF | (uint32_t)RTC_TAMPCR_TAMP3MF);
+
+ hrtc->Instance->TAMPCR |= tmpreg;
+
+ /* RTC Tamper Interrupt Configuration: EXTI configuration */
+ __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT();
+
+ EXTI->RTSR |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT;
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates Tamper.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Tamper: Selected tamper pin.
+ * This parameter can be RTC_Tamper_1 and/or RTC_TAMPER_2.
+ * @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 ((Tamper & RTC_TAMPER_1) != 0)
+ {
+ /* Disable the Tamper1 interrupt */
+ hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1);
+ }
+ if ((Tamper & RTC_TAMPER_2) != 0)
+ {
+ /* Disable the Tamper2 interrupt */
+ hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2);
+ }
+ if ((Tamper & RTC_TAMPER_3) != 0)
+ {
+ /* Disable the Tamper2 interrupt */
+ hrtc->Instance->TAMPCR &= (uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3);
+ }
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles TimeStamp interrupt request.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ if(__HAL_RTC_TIMESTAMP_GET_IT(hrtc, RTC_IT_TS))
+ {
+ /* Get the status of the Interrupt */
+ if((uint32_t)(hrtc->Instance->CR & RTC_IT_TS) != (uint32_t)RESET)
+ {
+ /* TIMESTAMP callback */
+ HAL_RTCEx_TimeStampEventCallback(hrtc);
+
+ /* Clear the TIMESTAMP interrupt pending bit */
+ __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc,RTC_FLAG_TSF);
+ }
+ }
+
+ /* Get the status of the Interrupt */
+ if(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F)== SET)
+ {
+ /* Get the TAMPER Interrupt enable bit and pending bit */
+ if((((hrtc->Instance->TAMPCR & RTC_TAMPCR_TAMPIE)) != (uint32_t)RESET) || \
+ (((hrtc->Instance->TAMPCR & RTC_TAMPCR_TAMP1IE)) != (uint32_t)RESET))
+ {
+ /* Tamper callback */
+ HAL_RTCEx_Tamper1EventCallback(hrtc);
+
+ /* Clear the Tamper interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc,RTC_FLAG_TAMP1F);
+ }
+ }
+
+ /* Get the status of the Interrupt */
+ if(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F)== SET)
+ {
+ /* Get the TAMPER Interrupt enable bit and pending bit */
+ if((((hrtc->Instance->TAMPCR & RTC_TAMPCR_TAMPIE)) != (uint32_t)RESET) || \
+ (((hrtc->Instance->TAMPCR & RTC_TAMPCR_TAMP2IE)) != (uint32_t)RESET))
+ {
+ /* Tamper callback */
+ HAL_RTCEx_Tamper2EventCallback(hrtc);
+
+ /* Clear the Tamper interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F);
+ }
+ }
+
+ /* Get the status of the Interrupt */
+ if(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F)== SET)
+ {
+ /* Get the TAMPER Interrupt enable bit and pending bit */
+ if((((hrtc->Instance->TAMPCR & RTC_TAMPCR_TAMPIE)) != (uint32_t)RESET) || \
+ (((hrtc->Instance->TAMPCR & RTC_TAMPCR_TAMP3IE)) != (uint32_t)RESET))
+ {
+ /* Tamper callback */
+ HAL_RTCEx_Tamper3EventCallback(hrtc);
+
+ /* Clear the Tamper interrupt pending bit */
+ __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F);
+ }
+ }
+
+ /* 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: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTC_TimeStampEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tamper 1 callback.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTC_Tamper1EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tamper 2 callback.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTC_Tamper2EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tamper 3 callback.
+ * @param hrtc: RTC handle
+ * @retval None
+ */
+__weak void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTCEx_Tamper3EventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function handles TimeStamp polling request.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == RESET)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
+ {
+ hrtc->State = HAL_RTC_STATE_TIMEOUT;
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ 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;
+ }
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles Tamper1 Polling.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ 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;
+}
+
+/**
+ * @brief This function handles Tamper2 Polling.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ 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;
+}
+
+/**
+ * @brief This function handles Tamper3 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;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTCEx_Group2 RTC Wake-up functions
+ * @brief RTC Wake-up functions
+ *
+@verbatim
+ ===============================================================================
+ ##### RTC Wake-up functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure Wake-up feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets wake up timer.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @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);
+
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /*Check RTC WUTWF flag is reset only when wake up timer enabled*/
+ if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET)
+ {
+ /* 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 Sets wake up timer with interrupt
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @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);
+
+ __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /*Check RTC WUTWF flag is reset only when wake up timer enabled*/
+ if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET)
+ {
+ /* 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();
+
+ EXTI->RTSR |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT;
+
+ /* Configure the Interrupt in the RTC_CR register */
+ __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc,RTC_IT_WUT);
+
+ /* Enable the Wakeup Timer */
+ __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates wake up timer counter.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @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);
+
+ /* Get tick */
+ 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 Gets wake up timer counter.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval Counter value
+ */
+uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc)
+{
+ /* Get the counter value */
+ return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT));
+}
+
+/**
+ * @brief This function handles Wake Up Timer interrupt request.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc)
+{
+ if(__HAL_RTC_WAKEUPTIMER_GET_IT(hrtc, RTC_IT_WUT))
+ {
+ /* Get the status of the Interrupt */
+ if((uint32_t)(hrtc->Instance->CR & RTC_IT_WUT) != (uint32_t)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: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTC_WakeUpTimerEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function handles Wake Up Timer Polling.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ 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_Group3 Extension Peripheral Control functions
+ * @brief Extension Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extension 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 Writes a data in a specified RTC Backup data register.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param BackupRegister: RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to
+ * specify the register.
+ * @param Data: Data to be written in the specified RTC Backup data register.
+ * @retval None
+ */
+void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
+{
+ uint32_t tmp = 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 Reads data from the specified RTC Backup data Register.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param BackupRegister: RTC Backup data Register number.
+ * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to
+ * specify the register.
+ * @retval Read value
+ */
+uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
+{
+ uint32_t tmp = 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 Sets the Smooth calibration parameters.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param SmoothCalibPeriod: Select the Smooth Calibration Period.
+ * This parameter can be can be one of the following values :
+ * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s.
+ * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s.
+ * @param SmoothCalibPlusPulses: Select to Set or reset the CALP bit.
+ * This parameter can be one of the following values:
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulses every 2*11 pulses.
+ * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added.
+ * @param SmouthCalibMinusPulsesValue: 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
+ * SmouthCalibMinusPulsesValue must be equal to 0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef* hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmouthCalibMinusPulsesValue)
+{
+ 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(SmouthCalibMinusPulsesValue));
+
+ /* 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)
+ {
+ /* Get tick */
+ 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)SmouthCalibMinusPulsesValue);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the Synchronization Shift Control Settings.
+ * @note When REFCKON is set, firmware must not write to Shift control register.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param ShiftAdd1S: Select to add or not 1 second to the time calendar.
+ * This parameter can be one of the following values :
+ * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar.
+ * @arg RTC_SHIFTADD1S_RESET: No effect.
+ * @param ShiftSubFS: Select the number of Second Fractions to substitute.
+ * This parameter can be one any value from 0 to 0x7FFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef* hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS)
+{
+ uint32_t tickstart = 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);
+
+ /* Get tick */
+ 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 Configures the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param CalibOutput: Select the Calibration output Selection .
+ * This parameter can be one of the following values:
+ * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz.
+ * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef* hrtc, uint32_t CalibOutput)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput));
+
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Clear flags before config */
+ hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL;
+
+ /* Configure the RTC_CR register */
+ hrtc->Instance->CR |= (uint32_t)CalibOutput;
+
+ __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivates the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz).
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc);
+
+ /* Enable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ /* Change RTC state */
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hrtc);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enables the RTC reference clock detection.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef* hrtc)
+{
+ /* 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: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @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 Enables the Bypass Shadow feature.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Set the BYPSHAD bit */
+ hrtc->Instance->CR |= (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 Disables the Bypass Shadow feature.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @note When the Bypass Shadow is enabled the calendar value are taken
+ * directly from the Calendar counter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef* hrtc)
+{
+ /* Process Locked */
+ __HAL_LOCK(hrtc);
+
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ /* Disable the write protection for RTC registers */
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ /* Reset the BYPSHAD bit */
+ hrtc->Instance->CR &= (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_Group4 Extended features functions
+ * @brief Extended features functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) RTC Alram B callback
+ (+) RTC Poll for Alarm B request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Alarm B callback.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @retval None
+ */
+__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_RTC_AlarmBEventCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function handles AlarmB Polling request.
+ * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
+ * the configuration information for RTC.
+ * @param Timeout: Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
+{
+ uint32_t tickstart = 0;
+
+ /* Get tick */
+ 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/f7/src/stm32f7xx_hal_sd.c b/stmhal/hal/f7/src/stm32f7xx_hal_sd.c
new file mode 100644
index 0000000000..4aa28dbfdf
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_sd.c
@@ -0,0 +1,3381 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_sd.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 (SDMMC 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 SDMMC low level resources by implement the HAL_SD_MspInit() API:
+ (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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 -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup SD_Private_Functions SD Private Functions
+ * @{
+ */
+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 create 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;
+
+ /* Allocate lock resource and initialize it */
+ hsd->Lock = HAL_UNLOCKED;
+
+ /* 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)
+{
+ /* 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)
+{
+ /* 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;
+
+ /* 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;
+
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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 = ((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 od 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/f7/src/stm32f7xx_hal_spi.c b/stmhal/hal/f7/src/stm32f7xx_hal_spi.c
new file mode 100644
index 0000000000..999877937f
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_spi.c
@@ -0,0 +1,2728 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_spi.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 customised 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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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 macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup 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 Initializes the SPI according to the specified parameters
+ * in the SPI_InitTypeDef and create 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 DeInitializes 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;
+
+ /* check flag before the SPI disable */
+ SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FTLVL, SPI_FTLVL_EMPTY, SPI_DEFAULT_TIMEOUT);
+ SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT);
+ SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT);
+
+ /* 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 SPI MSP Init
+ * @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)
+ {
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SPI_MspInit should be implemented in the user file
+ */
+}
+
+/**
+ * @brief SPI MSP DeInit
+ * @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)
+{
+ /* 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)
+{
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_BUSY;
+ }
+
+ if((pData == NULL ) || (Size == 0))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_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(SPI_WaitFlagStateUntilTimeout(hspi,SPI_FLAG_TXE,SPI_FLAG_TXE,Timeout) != HAL_OK)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount--;
+ }
+ }
+ /* Transmit data in 8 Bit mode */
+ else
+ {
+ while (hspi->TxXferCount > 0)
+ {
+ if(hspi->TxXferCount != 0x1)
+ {
+ /* Wait until TXE flag is set to send data */
+ if(SPI_WaitFlagStateUntilTimeout(hspi,SPI_FLAG_TXE,SPI_FLAG_TXE,Timeout) != HAL_OK)
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
+ hspi->pTxBuffPtr += sizeof(uint16_t);
+ hspi->TxXferCount -= 2;
+ }
+ else
+ {
+ /* Wait until TXE flag is set to send data */
+ if(SPI_WaitFlagStateUntilTimeout(hspi,SPI_FLAG_TXE,SPI_FLAG_TXE,Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ *((__IO uint8_t*)&hspi->Instance->DR) = (*hspi->pTxBuffPtr++);
+ hspi->TxXferCount--;
+ }
+ }
+ }
+
+ /* 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)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Clear OVERUN flag in 2 Lines communication mode because received is not read */
+ if(hspi->Init.Direction == SPI_DIRECTION_2LINES)
+ {
+ __HAL_SPI_CLEAR_OVRFLAG(hspi);
+ }
+
+ hspi->State = HAL_SPI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pData: pointer to data buffer
+ * @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;
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if((pData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ 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 */
+ return HAL_SPI_TransmitReceive(hspi,pData,pData,Size,Timeout);
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ 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 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);
+ }
+
+ /* 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);
+ }
+
+ /* Receive data in 8 Bit mode */
+ if(hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+ {
+ while(hspi->RxXferCount > 1)
+ {
+ /* Wait until the RXNE flag */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ (*hspi->pRxBuffPtr++)= *(__IO uint8_t *)&hspi->Instance->DR;
+ hspi->RxXferCount--;
+ }
+ }
+ else /* Receive data in 16 Bit mode */
+ {
+ while(hspi->RxXferCount > 1 )
+ {
+ /* Wait until RXNE flag is reset to read data */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ hspi->RxXferCount--;
+ }
+ }
+
+ /* Enable CRC Transmission */
+ if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+ {
+ hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
+ }
+
+ /* Wait until RXNE flag is set */
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SPI_FLAG_RXNE, Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ /* Receive last data in 16 Bit mode */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+ {
+ *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
+ hspi->pRxBuffPtr += sizeof(uint16_t);
+ }
+ /* Receive last data in 8 Bit mode */
+ else
+ {
+ (*hspi->pRxBuffPtr++) = *(__IO uint8_t *)&hspi->Instance->DR;
+ }
+ hspi->RxXferCount--;
+
+ /* 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;
+ }
+ 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.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_FLAG;
+ }
+ 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)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+ return HAL_ERROR;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in blocking mode
+ * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
+ * the configuration information for SPI module.
+ * @param pTxData: pointer to transmission data buffer
+ * @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 = 0;
+ uint32_t tickstart = HAL_GetTick();
+
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ 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))
+ {
+ SET_BIT(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)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ /* 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))
+ {
+ SET_BIT(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 fiforxthreshold 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)
+ {
+ if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
+ {
+ hspi->State = HAL_SPI_STATE_READY;
+ __HAL_UNLOCK(hspi);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /* 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;
+ }
+
+ 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;
+ }
+ tmpreg = *(__IO uint8_t *)&hspi->Instance->DR;
+ UNUSED(tmpreg); /* To avoid GCC warning */
+ }
+ }
+ }
+
+ /* Check the end of the transaction */
+ if(SPI_EndRxTxTransaction(hspi,Timeout) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ 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;
+ /* Clear CRC Flag */
+ __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_ERROR;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ if(hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in no-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)
+{
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ if(hspi->State == HAL_SPI_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ hspi->State = HAL_SPI_STATE_BUSY_TX;
+ hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+ hspi->pTxBuffPtr = pData;
+ hspi->TxXferSize = Size;
+ hspi->TxXferCount = Size;
+ hspi->pRxBuffPtr = NULL;
+ hspi->RxXferSize = 0;
+ hspi->RxXferCount = 0;
+
+ /* Set the function for IT treatement */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
+ {
+ hspi->RxISR = NULL;
+ hspi->TxISR = SPI_TxISR_16BIT;
+ }
+ else
+ {
+ hspi->RxISR = NULL;
+ 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));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ /* Note : The SPI must be enabled after unlocking current process
+ to avoid the risk of SPI interrupt handle execution before current
+ process unlock */
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in no-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)
+{
+ if(hspi->State == HAL_SPI_STATE_READY)
+ {
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ /* 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 = 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;
+ }
+
+ /* check the data size to adapt Rx threshold and the set the function for IT treatment */
+ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
+ {
+ /* set fiforxthreshold according the reception data length: 16 bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_RxISR_16BIT;
+ hspi->TxISR = NULL;
+ }
+ else
+ {
+ /* set fiforxthreshold according the reception data length: 8 bit */
+ SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ hspi->RxISR = SPI_RxISR_8BIT;
+ hspi->TxISR = NULL;
+ }
+
+ /* 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));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ /* Note : The SPI must be enabled after unlocking current process
+ to avoid the risk of SPI interrupt handle execution before current
+ process unlock */
+
+ /* Check if the SPI is already enabled */
+ if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+ {
+ /* Enable SPI peripheral */
+ __HAL_SPI_ENABLE(hspi);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in no-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)
+{
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ 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)))
+ {
+ if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ 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 treatement */
+ 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 fiforxthreshold according the reception data length: 16 bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+ }
+ else
+ {
+ /* set fiforxthreshold 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));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(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);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in no-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)
+{
+ assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ 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 */
+ hspi->Instance->CR2 |= SPI_CR2_TXDMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hspi);
+
+ return HAL_OK;
+}
+
+/**
+* @brief Receive an amount of data in no-blocking mode with DMA
+* @param hspi: SPI handle
+* @param pData: pointer to data buffer
+* @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)
+{
+ if(hspi->State != HAL_SPI_STATE_READY)
+ {
+ return HAL_BUSY;
+ }
+
+ if((pData == NULL) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hspi);
+
+ 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))
+ {
+ /* Process Locked */
+ __HAL_UNLOCK(hspi);
+ /* Restriction the DMA data received is not allowed in this mode */
+ return HAL_ERROR;
+ }
+
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+ 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 fiforxthreshold 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 */
+ 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);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(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);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmit and Receive an amount of data in no-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)
+{
+ assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+ 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)))
+ {
+ if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hspi);
+
+ /* 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);
+ CLEAR_BIT(hspi->Instance->CR2, 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 fiforxthreshold 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 fiforxthreshold according the reception data length: 16bit */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+ /* Size must include the CRC length */
+ 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 because the last generated transfer request is
+ the reception request (RXNE) */
+ if(hspi->State == HAL_SPI_STATE_BUSY_RX)
+ {
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+ }
+ else
+ {
+ hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
+ hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
+ }
+ /* Set the DMA error callback */
+ hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+ /* Enable Rx DMA Request */
+ 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;
+
+ if(hspi->State == HAL_SPI_STATE_BUSY_TX_RX)
+ {
+ /* Set the DMA error callback */
+ hspi->hdmatx->XferErrorCallback = SPI_DMAError;
+ }
+ else
+ {
+ hspi->hdmatx->XferErrorCallback = NULL;
+ }
+
+ /* Enable the Tx DMA channel */
+ HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(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);
+ }
+
+ /* Enable Tx DMA Request */
+ hspi->Instance->CR2 |= SPI_CR2_TXDMAEN;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Pauses 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 Resumes 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 Stops 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 Stream */
+ if(hspi->hdmatx != NULL)
+ {
+ HAL_DMA_Abort(hspi->hdmatx);
+ }
+ /* Abort the SPI DMA rx Stream */
+ 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 This function handles 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)
+{
+ /* SPI in mode Receiver ----------------------------------------------------*/
+ if((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_OVR) == RESET) &&
+ (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE) != RESET) && (__HAL_SPI_GET_IT_SOURCE(hspi, SPI_IT_RXNE) != RESET))
+ {
+ hspi->RxISR(hspi);
+ return;
+ }
+
+ /* SPI in mode Transmitter ---------------------------------------------------*/
+ if((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) != RESET) && (__HAL_SPI_GET_IT_SOURCE(hspi, SPI_IT_TXE) != RESET))
+ {
+ hspi->TxISR(hspi);
+ return;
+ }
+
+ /* SPI in ERROR Treatment ---------------------------------------------------*/
+ if((hspi->Instance->SR & (SPI_FLAG_MODF | SPI_FLAG_OVR | SPI_FLAG_FRE)) != RESET)
+ {
+ /* SPI Overrun error interrupt occurred -------------------------------------*/
+ if(__HAL_SPI_GET_FLAG(hspi, 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(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_MODF) != RESET)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_MODF;
+ __HAL_SPI_CLEAR_MODFFLAG(hspi);
+ }
+
+ /* SPI Frame error interrupt occurred ----------------------------------------*/
+ if(__HAL_SPI_GET_FLAG(hspi, 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)
+{
+ /* 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 callbacks
+ * @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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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)
+{
+ /* 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 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 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;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Private_Functions SPI 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;
+
+ /* DMA Normal Mode */
+ if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
+ {
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ /* Clear OVERUN 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)
+{
+ __IO uint16_t tmpreg;
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* DMA Normal mode */
+ if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
+ {
+ /* 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 DMA Request */
+ hspi->Instance->CR2 &= (uint32_t)(~SPI_CR2_RXDMAEN);
+ /* Disable Tx DMA Request (done by default to handle the case master rx direction 2 lines) */
+ hspi->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
+
+ /* Check the end of the transaction */
+ SPI_EndRxTransaction(hspi,SPI_DEFAULT_TIMEOUT);
+
+ 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);
+ HAL_SPI_RxCpltCallback(hspi);
+ }
+ else
+ {
+ if(hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_RxCpltCallback(hspi);
+ }
+ else
+ {
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ }
+ }
+ else
+ {
+ 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)
+{
+ __IO int16_t tmpreg;
+ SPI_HandleTypeDef* hspi = ( SPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
+
+ /* 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 */
+ SPI_EndRxTxTransaction(hspi,SPI_DEFAULT_TIMEOUT);
+
+ /* Disable Tx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+ /* Disable Rx DMA Request */
+ CLEAR_BIT(hspi->Instance->CR2, 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);
+ HAL_SPI_ErrorCallback(hspi);
+ }
+ else
+ {
+ if(hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+ {
+ HAL_SPI_TxRxCpltCallback(hspi);
+ }
+ else
+ {
+ HAL_SPI_ErrorCallback(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 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 fiforxthreshold 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 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;
+
+ 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 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 16Bit 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 16bit 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 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 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;
+ tmpreg = *((__IO 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 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 16bit 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 16Bit 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 8Bit 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 16Bit 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 This function handles 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 This function handles SPI 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 This function handles 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);
+ }
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+ 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 This function handles 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)
+{
+ /* Procedure to check the transaction complete */
+ if(SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FTLVL, SPI_FTLVL_EMPTY, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+ if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout) != HAL_OK)
+ {
+ hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
+ return HAL_TIMEOUT;
+ }
+ 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 This function handles the close 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 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 This function handles the close 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 */
+ SPI_EndRxTransaction(hspi,SPI_DEFAULT_TIMEOUT);
+
+ 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 This function handles the close 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));
+
+ /* Clear OVERUN 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/f7/src/stm32f7xx_hal_tim.c b/stmhal/hal/f7/src/stm32f7xx_hal_tim.c
new file mode 100644
index 0000000000..147cd670fb
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_tim.c
@@ -0,0 +1,5459 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_tim.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 from feature used :
+ (++) 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 __TIMx_CLK_ENABLE();
+ (##) TIM pins configuration
+ (+++) Enable the clock for the TIM GPIOs using the following function:
+ __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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup TIM TIM
+ * @brief TIM HAL module driver
+ * @{
+ */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup TIM_Private_Functions
+ * @{
+ */
+/* 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 TIM_ITRx);
+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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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)
+ {
+ /* 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 DeInitializes the TIM Base peripheral
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIM_Base_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Base MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 DeInitializes the TIM peripheral
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIM_OC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Output Compare MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Channel: TIM Channel to be enabled.
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Start(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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Channel: TIM Channel to be disabled.
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop(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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Channel: TIM Channel to be enabled.
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Channel: TIM Channel to be disabled.
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Channel: TIM Channel to be enabled.
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @param pData: The source Buffer address.
+ * @param Length: The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Channel: TIM Channel to be disabled.
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* 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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 DeInitializes the TIM peripheral
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIM_PWM_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM PWM MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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(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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 DeInitializes the TIM peripheral
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIM_IC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Input Capture MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 DeInitializes the TIM One Pulse
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIM_OnePulse_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM One Pulse MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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)
+{
+ /* 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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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)
+{
+ /* 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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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)
+{
+ /* 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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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)
+{
+ /* 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_ADVANCED_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 DeInitializes the TIM Encoder interface
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIM_Encoder_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Encoder Interface MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError;
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Break input event */
+ if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK2) != RESET)
+ {
+ if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET)
+ {
+ __HAL_TIM_CLEAR_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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
+ * @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));
+ assert_param(IS_TIM_OCN_POLARITY(sConfig->OCNPolarity));
+ assert_param(IS_TIM_OCNIDLE_STATE(sConfig->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(sConfig->OCIdleState));
+
+ /* 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_OCN_POLARITY(sConfig->OCNPolarity));
+ assert_param(IS_TIM_OCNIDLE_STATE(sConfig->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(sConfig->OCIdleState));
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output compare configuration from sConfig structure */
+ temp1.OCMode = sConfig->OCMode;
+ temp1.Pulse = sConfig->Pulse;
+ temp1.OCPolarity = sConfig->OCPolarity;
+ temp1.OCNPolarity = sConfig->OCNPolarity;
+ temp1.OCIdleState = sConfig->OCIdleState;
+ temp1.OCNIdleState = sConfig->OCNIdleState;
+
+ switch (OutputChannel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ TIM_OC1_SetConfig(htim->Instance, &temp1);
+ }
+ break;
+ case TIM_CHANNEL_2:
+ {
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ TIM_OC2_SetConfig(htim->Instance, &temp1);
+ }
+ break;
+ default:
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIMEx_DMACommutationCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMACaptureCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIMEx_DMACommutationCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param EventSource: specifies the event source.
+ * This parameter can be one of the following values:
+ * @arg TIM_EVENTSOURCE_UPDATE: Timer update Event source
+ * @arg TIM_EVENTSOURCE_CC1: Timer Capture Compare 1 Event source
+ * @arg TIM_EVENTSOURCE_CC2: Timer Capture Compare 2 Event source
+ * @arg TIM_EVENTSOURCE_CC3: Timer Capture Compare 3 Event source
+ * @arg TIM_EVENTSOURCE_CC4: Timer Capture Compare 4 Event source
+ * @arg TIM_EVENTSOURCE_COM: Timer COM event source
+ * @arg TIM_EVENTSOURCE_TRIGGER: Timer Trigger Event source
+ * @arg TIM_EVENTSOURCE_BREAK: Timer Break event source
+ * @arg TIM_EVENTSOURCE_BREAK2: Timer Break2 event source
+ * @note TIM6 and TIM7 can only generate an update event.
+ * @note TIM_EVENTSOURCE_COM, TIM_EVENTSOURCE_BREAK and TIM_EVENTSOURCE_BREAK2 are used only with TIM1 and TIM8.
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_EVENT_SOURCE(EventSource));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ /* Change the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Set the event sources */
+ htim->Instance->EGR = EventSource;
+
+ /* Change the TIM state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the OCRef clear feature
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 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_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)
+ {
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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));
+ assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+ assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+ assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+ /* 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:
+ {
+ assert_param(IS_TIM_ETR_INSTANCE(htim->Instance));
+ /* 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:
+ {
+ assert_param(IS_TIM_ETR_INSTANCE(htim->Instance));
+ /* 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:
+ {
+ assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+ TIM_TI1_ConfigInputStage(htim->Instance,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1);
+ }
+ break;
+ case TIM_CLOCKSOURCE_TI2:
+ {
+ assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+ TIM_TI2_ConfigInputStage(htim->Instance,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2);
+ }
+ break;
+ case TIM_CLOCKSOURCE_TI1ED:
+ {
+ assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+ TIM_TI1_ConfigInputStage(htim->Instance,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED);
+ }
+ break;
+ case TIM_CLOCKSOURCE_ITR0:
+ {
+ assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0);
+ }
+ break;
+ case TIM_CLOCKSOURCE_ITR1:
+ {
+ assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1);
+ }
+ break;
+ case TIM_CLOCKSOURCE_ITR2:
+ {
+ assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2);
+ }
+ break;
+ case TIM_CLOCKSOURCE_ITR3:
+ {
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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)
+{
+ uint32_t tmpsmcr = 0;
+ uint32_t tmpccmr1 = 0;
+ uint32_t tmpccer = 0;
+
+ /* 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;
+
+ /* 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_ETR_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;
+ }
+
+ 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *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 state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM OC state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM PWM state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Input Capture state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM One Pulse Mode state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Encoder Mode state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void HAL_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 a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void HAL_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 a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void HAL_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 a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @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 a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @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: pointer on TIM Time Base required parameters
+ * @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_CC3_INSTANCE(TIMx) != RESET)
+ {
+ /* Select the Counter Mode */
+ tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
+ tmpcr1 |= Structure->CounterMode;
+ }
+
+ if(IS_TIM_CC1_INSTANCE(TIMx) != RESET)
+ {
+ /* Set the clock division */
+ tmpcr1 &= ~TIM_CR1_CKD;
+ tmpcr1 |= (uint32_t)Structure->ClockDivision;
+ }
+
+ TIMx->CR1 = tmpcr1;
+
+ /* Set the Auto-reload value */
+ TIMx->ARR = (uint32_t)Structure->Period ;
+
+ /* Set the Prescaler value */
+ TIMx->PSC = (uint32_t)Structure->Prescaler;
+
+ if(IS_TIM_ADVANCED_INSTANCE(TIMx) != RESET)
+ {
+ /* 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 Output Compare 1 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The output 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_ADVANCED_INSTANCE(TIMx) != RESET)
+ {
+ /* 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;
+
+ /* 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 Output Compare 2 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The output configuration structure
+ * @retval None
+ */
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, 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_ADVANCED_INSTANCE(TIMx) != RESET)
+ {
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* 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;
+
+ /* 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 Output Compare 3 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The output 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_ADVANCED_INSTANCE(TIMx) != RESET)
+ {
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* 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;
+
+ /* 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 Output Compare 4 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The output 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((TIMx == TIM1) || (TIMx == TIM8))*/
+ if(IS_TIM_ADVANCED_INSTANCE(TIMx) != RESET)
+ {
+ 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;
+}
+
+/**
+ * @brief Time Output Compare 4 configuration
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param sSlaveConfig: The slave configuration structure
+ * @retval None
+ */
+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_ETR_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_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+ 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.
+ * @retval None
+ * @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.
+ */
+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 TIM_ITRx: 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 TIM_ITRx)
+{
+ 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 |= TIM_ITRx | 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_ExtTRGPSC_DIV1: ETRP Prescaler OFF.
+ * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
+ * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
+ * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
+ * @param TIM_ExtTRGPolarity: The external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
+ * @arg TIM_ExtTRGPolarity_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/f7/src/stm32f7xx_hal_tim_ex.c b/stmhal/hal/f7/src/stm32f7xx_hal_tim_ex.c
new file mode 100644
index 0000000000..0252db920f
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_tim_ex.c
@@ -0,0 +1,2481 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_tim_ex.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief TIM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Timer extension peripheral:
+ * + Time Hall Sensor Interface Initialization
+ * + Time Hall Sensor Interface Start
+ * + Time Complementary signal bread 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 Extension features include:
+ (#) Complementary outputs with programmable dead-time for :
+ (++) Input Capture
+ (++) Output Compare
+ (++) PWM generation (Edge and Center-aligned Mode)
+ (++) One-pulse mode output
+ (#) Synchronization circuit to control the timer with external signals and to
+ interconnect several timers together.
+ (#) 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 from feature used :
+ (++) Complementary Output Compare : HAL_TIM_OC_MspInit()
+ (++) Complementary PWM generation : HAL_TIM_PWM_MspInit()
+ (++) Complementary One-pulse mode output : HAL_TIM_OnePulse_MspInit()
+ (++) Hall Sensor output : HAL_TIM_HallSensor_MspInit()
+
+ (#) Initialize the TIM low level resources :
+ (##) Enable the TIM interface clock using __TIMx_CLK_ENABLE();
+ (##) TIM pins configuration
+ (+++) Enable the clock for the TIM GPIOs using the following function:
+ __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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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)
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup TIMEx_Private_Functions
+ * @{
+ */
+static void TIM_CCxNChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelNState);
+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);
+/**
+ * @}
+ */
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup TIMEx_Exported_Functions TIMEx 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 create the associated handle.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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));
+
+ /* Set the TIM state */
+ htim->State= HAL_TIM_STATE_BUSY;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIMEx_HallSensor_MspInit(htim);
+
+ /* 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 DeInitializes the TIM Hall Sensor interface
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Hall Sensor MSP.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMACaptureCplt;
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 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 on the complementary
+ * output.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 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
+ * on the complementary output.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 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
+ * on the complementary output.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 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 on the complementary output.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 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 on the
+ * complementary output.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 = HAL_TIM_DMADelayPulseCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = HAL_TIM_DMAError ;
+
+ /* Enable the DMA Stream */
+ 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 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 on the complementary
+ * output
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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 complemetary
+ * output.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+ }
+
+/**
+ * @brief Stops the TIM One Pulse signal generation in interrupt mode on the
+ * complementary channel.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 Output */
+ __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 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 commutation event in case of use of the Hall sensor interface.
+ (+) Configure the DMA Burst Mode.
+
+@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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_ADVANCED_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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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_ADVANCED_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 = HAL_TIMEx_DMACommutationCplt;
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = HAL_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));
+ assert_param(IS_TIM_OCN_POLARITY(sConfig->OCNPolarity));
+ assert_param(IS_TIM_OCNIDLE_STATE(sConfig->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(sConfig->OCIdleState));
+
+ /* 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_OCN_POLARITY(sConfig->OCNPolarity));
+ assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode));
+ assert_param(IS_TIM_OCNIDLE_STATE(sConfig->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(sConfig->OCIdleState));
+
+ /* 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:
+ {
+ /* 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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param sBreakDeadTimeConfig: pointer to a TIM_ConfigBreakDeadConfig_TypeDef 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));
+ assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State));
+ assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity));
+ assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* 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 */
+
+ /* 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;
+
+ /* Set TIMx_BDTR */
+ htim->Instance->BDTR = tmpbdtr;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the TIM2, TIM5 and TIM11 Remapping input capabilities.
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @param Remap: specifies the TIM input remapping source.
+ * This parameter can be one of the following values:
+ * @arg TIM_TIM2_TIM8_TRGO: TIM2 ITR1 input is connected to TIM8 Trigger output(default)
+ * @arg TIM_TIM2_ETH_PTP: TIM2 ITR1 input is connected to ETH PTP trigger output.
+ * @arg TIM_TIM2_USBFS_SOF: TIM2 ITR1 input is connected to USB FS SOF.
+ * @arg TIM_TIM2_USBHS_SOF: TIM2 ITR1 input is connected to USB HS SOF.
+ * @arg TIM_TIM5_GPIO: TIM5 CH4 input is connected to dedicated Timer pin(default)
+ * @arg TIM_TIM5_LSI: TIM5 CH4 input is connected to LSI clock.
+ * @arg TIM_TIM5_LSE: TIM5 CH4 input is connected to LSE clock.
+ * @arg TIM_TIM5_RTC: TIM5 CH4 input is connected to RTC Output event.
+ * @arg TIM_TIM11_GPIO: TIM11 CH4 input is connected to dedicated Timer pin(default)
+ * @arg TIM_TIM11_SPDIF: SPDIF Frame synchronous
+ * @arg TIM_TIM11_HSE: TIM11 CH4 input is connected to HSE_RTC clock
+ * (HSE divided by a programmable prescaler)
+ * @arg TIM_TIM11_MCO1: TIM11 CH1 input is connected to MCO1
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
+{
+ __HAL_LOCK(htim);
+
+ /* Check parameters */
+ assert_param(IS_TIM_REMAP_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_REMAP(Remap));
+
+ /* Set the Timer remapping configuration */
+ htim->Instance->OR = Remap;
+
+ 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 OCRef: 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 OCRef)
+{
+ /* Check parameters */
+ assert_param(IS_TIM_COMBINED3PHASEPWM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_GROUPCH5(OCRef));
+
+ /* 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 |= OCRef;
+
+ 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
+ ==============================================================================
+ ##### Extension Callbacks functions #####
+ ==============================================================================
+ [..]
+ This section provides Extension TIM callback functions:
+ (+) Timer Commutation callback
+ (+) Timer Break callback
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Hall commutation changed callback in non blocking mode
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *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: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *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
+ ==============================================================================
+ ##### Extension 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 state
+ * @param htim: pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @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 a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+void HAL_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;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ADVANCED_INSTANCE(TIMx));
+ assert_param(IS_TIM_COMPLEMENTARY_CHANNELS(Channel));
+
+ tmp = TIM_CCER_CC1NE << Channel;
+
+ /* Reset the CCxNE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxNE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelNState << Channel);
+}
+
+/**
+ * @brief Timer Output Compare 5 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The output configuration structure
+ * @retval None
+ */
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, 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 Output Compare 6 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config: The output configuration structure
+ * @retval None
+ */
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, 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;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_uart.c b/stmhal/hal/f7/src/stm32f7xx_hal_uart.c
new file mode 100644
index 0000000000..3f3b06f539
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_uart.c
@@ -0,0 +1,1996 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_hal_uart.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @brief UART HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Universal Asynchronous Receiver Transmitter (UART) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral Control functions
+ * + Peripheral State and Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The UART HAL driver can be used as follows:
+
+ (#) Declare a UART_HandleTypeDef handle structure.
+
+ (#) 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.
+ (##) 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 stream.
+ (+++) Enable the DMAx interface clock.
+ (+++) Configure the declared DMA handle structure with the required
+ Tx/Rx parameters.
+ (+++) Configure the DMA Tx/Rx Stream.
+ (+++) 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 Stream.
+
+ (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
+ flow control and Mode(Receiver/Transmitter) in the Init 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 LIN mode, initialize the UART registers by calling the HAL_LIN_Init() API.
+
+ (#) For the Multi-Processor mode, initialize the UART registers by calling
+ the HAL_MultiProcessor_Init() API.
+
+ [..]
+ (@) The specific UART interrupts (Transmission complete interrupt,
+ RXNE interrupt and Error Interrupts) will be managed using the macros
+ __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit
+ and receive process.
+
+ [..]
+ (@) These APIs (HAL_UART_Init() and HAL_HalfDuplex_Init()) configure also the
+ low level Hardware GPIO, CLOCK, CORTEX...etc) by calling the customized
+ HAL_UART_MspInit() API.
+
+ [..]
+ Three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_UART_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_UART_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non blocking mode using HAL_UART_Transmit_IT()
+ (+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_UART_TxCpltCallback
+ (+) Receive an amount of data in non blocking mode using HAL_UART_Receive_IT()
+ (+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_UART_RxCpltCallback
+ (+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_UART_ErrorCallback
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Send an amount of data in non blocking mode (DMA) using HAL_UART_Transmit_DMA()
+ (+) At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_UART_TxHalfCpltCallback
+ (+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_UART_TxCpltCallback
+ (+) Receive an amount of data in non blocking mode (DMA) using HAL_UART_Receive_DMA()
+ (+) At reception end of half transfer HAL_UART_RxHalfCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_UART_RxHalfCpltCallback
+ (+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can
+ add his own code by customization of function pointer HAL_UART_RxCpltCallback
+ (+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_UART_ErrorCallback
+ (+) Pause the DMA Transfer using HAL_UART_DMAPause()
+ (+) Resume the DMA Transfer using HAL_UART_DMAResume()
+ (+) Stop the DMA Transfer using HAL_UART_DMAStop()
+
+ *** UART HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in UART HAL driver.
+
+ (+) __HAL_UART_ENABLE: Enable the UART peripheral
+ (+) __HAL_UART_DISABLE: Disable the UART peripheral
+ (+) __HAL_UART_GET_FLAG : Check whether the specified UART flag is set or not
+ (+) __HAL_UART_CLEAR_IT : Clears the specified UART ISR flag
+ (+) __HAL_UART_ENABLE_IT: Enable the specified UART interrupt
+ (+) __HAL_UART_DISABLE_IT: Disable the specified UART interrupt
+ (+) __HAL_UART_GET_IT_SOURCE: Check whether the specified UART interrupt has occurred or not
+
+ [..]
+ (@) You can refer to the UART HAL driver header file for more useful macros
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup UART UART
+ * @brief HAL UART module driver
+ * @{
+ */
+#ifdef HAL_UART_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define HAL_UART_TXDMA_TIMEOUTVALUE 22000
+#define UART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \
+ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8))
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+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);
+/* Private 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 only these parameters 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.
+ Depending on the frame length defined by the M bit (8-bits or 9-bits),
+ please refer to Reference manual for possible UART frame formats.
+ (++) Hardware flow control
+ (++) Receiver/transmitter modes
+ (++) Over Sampling Method
+ [..]
+ The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init() and HAL_MultiProcessor_Init() APIs
+ follow respectively the UART asynchronous, UART Half duplex, LIN and Multi-Processor
+ configuration procedures (details for the procedures are available in reference manual (RM0329)).
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the UART 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_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));
+ }
+
+ 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 Initializes 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;
+ }
+
+ 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 Initializes 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 UART_LINBREAKDETECTLENGTH_10B: 10-bit break detection
+ * @arg 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 parameters */
+ assert_param(IS_UART_INSTANCE(huart->Instance));
+ assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength));
+ assert_param(IS_LIN_WORD_LENGTH(huart->Init.WordLength));
+
+ 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 Initializes the multiprocessor mode according to the specified
+ * parameters in the UART_InitTypeDef and creates 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 UART_WAKEUPMETHOD_IDLELINE: WakeUp by an idle line detection
+ * @arg 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
+ * @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 DeInitializes 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));
+
+ 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 UART MSP Init
+ * @param huart: uart handle
+ * @retval None
+ */
+ __weak void HAL_UART_MspInit(UART_HandleTypeDef *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 UART MSP DeInit
+ * @param huart: uart handle
+ * @retval None
+ */
+ __weak void HAL_UART_MspDeInit(UART_HandleTypeDef *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()
+ (+) UART_Transmit_IT()
+ (+) UART_Receive_IT()
+
+ (#) 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;
+ }
+
+ /* 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 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 SR register by writing 0 to it */
+ __HAL_UART_CLEAR_IT(huart, UART_FLAG_TC);
+
+
+ /* 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 Pauses the DMA Transfer.
+ * @param huart: UART handle
+ * @retval None
+ */
+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 Resumes the DMA Transfer.
+ * @param huart: UART handle
+ * @retval None
+ */
+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_IT(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_IT(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;
+ }
+
+ /* If the UART peripheral is still not enabled, enable it */
+ if ((huart->Instance->CR1 & USART_CR1_UE) == 0)
+ {
+ /* Enable UART peripheral */
+ __HAL_UART_ENABLE(huart);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the DMA Transfer.
+ * @param huart: UART handle
+ * @retval None
+ */
+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 This function handles 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_PEFLAG(huart);
+
+ 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_FEFLAG(huart);
+
+ 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_NEFLAG(huart);
+
+ 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_OREFLAG(huart);
+
+ 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 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);
+ /* Clear RXNE interrupt flag */
+ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
+ }
+
+
+ /* 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 This function handles UART Communication Timeout.
+ * @param huart: UART handle
+ * @param Flag: specifies the UART flag to check.
+ * @param Status: The new 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 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((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
+ {
+ huart->TxXferCount = 0;
+
+ /* Disable the DMA transfer for transmit request by setting 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((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
+ {
+ huart->RxXferCount = 0;
+
+ /* Disable the DMA transfer for the receiver request by setting 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 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 Tx Transfer completed callbacks
+ * @param huart: uart handle
+ * @retval None
+ */
+ __weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *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 callbacks.
+ * @param huart: UART handle
+ * @retval None
+ */
+ __weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *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 callbacks
+ * @param huart: uart handle
+ * @retval None
+ */
+__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *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 callbacks.
+ * @param huart: UART handle
+ * @retval None
+ */
+__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *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 callbacks
+ * @param huart: uart handle
+ * @retval None
+ */
+ __weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_UART_ErrorCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief Send an amount of data in interrupt mode
+ * Function 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);
+
+ /* 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;
+ }
+
+ /* Wait on TC flag to be able to start a second transfer */
+ if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ HAL_UART_TxCpltCallback(huart);
+
+ 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
+ * Function 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
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @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_UART_GetState() API is helpful to check in run-time the state of the UART peripheral.
+ (+) 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
+ (+) 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 (doesn't 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 (doesn't mean it actually wakes up the software,
+ * 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).
+ * To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called.
+ * @param huart: uart handle
+ * @retval HAL status
+ */
+void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart)
+{
+ __HAL_UART_SEND_REQ(huart, UART_MUTE_MODE_REQUEST);
+}
+
+
+
+/**
+ * @brief return the UART state
+ * @param huart: uart handle
+ * @retval HAL state
+ */
+HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart)
+{
+ return huart->State;
+}
+
+/**
+* @brief Return the UART 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;
+}
+
+/**
+ * @brief Configure the UART peripheral
+ * @param huart: uart handle
+ * @retval None
+ */
+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));
+ assert_param(IS_UART_STOPBITS(huart->Init.StopBits));
+ 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_ONE_BIT_SAMPLE(huart->Init.OneBitSampling));
+
+
+ /*-------------------------- 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 */
+ tmpreg = (uint32_t)huart->Init.HwFlowCtl | 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 UART Over Sampling to set Baud Rate Register */
+ 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_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 Enables the UART transmitter and disables the UART receiver.
+ * @param huart: UART handle
+ * @retval HAL status
+ * @retval None
+ */
+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 Enables the UART receiver and disables 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 Transmits break characters.
+ * @param huart: UART handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart)
+{
+ /* Check the parameters */
+ assert_param(IS_UART_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;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_UART_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_ll_sdmmc.c b/stmhal/hal/f7/src/stm32f7xx_ll_sdmmc.c
new file mode 100644
index 0000000000..b14445c686
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_ll_sdmmc.c
@@ -0,0 +1,510 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_ll_sdmmc.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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 databus 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 of PLL
+ (PLL48CLK). 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(), DIO_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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SDMMC_LL SDMMC Low Layer
+ * @brief Low layer module for SD
+ * @{
+ */
+
+#if defined (HAL_SD_MODULE_ENABLED) || defined(HAL_MMC_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 create 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)
+{
+ uint32_t tmpreg = 0;
+
+ /* 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 */
+ tmpreg |= (Init.ClockEdge |\
+ Init.ClockBypass |\
+ Init.ClockPowerSave |\
+ Init.BusWide |\
+ Init.HardwareFlowControl |\
+ Init.ClockDiv
+ );
+
+ /* Write to SDMMC CLKCR */
+ MODIFY_REG(SDMMCx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
+
+ 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)
+{
+ uint32_t tmpreg = 0;
+
+ /* 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 */
+ tmpreg |= (uint32_t)(Command->CmdIndex |\
+ Command->Response |\
+ Command->WaitForInterrupt |\
+ Command->CPSM);
+
+ /* Write to SDMMC CMD register */
+ MODIFY_REG(SDMMCx->CMD, CMD_CLEAR_MASK, tmpreg);
+
+ 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)
+{
+ uint32_t tmpreg = 0;
+
+ /* 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 */
+ tmpreg |= (uint32_t)(Data->DataBlockSize |\
+ Data->TransferDir |\
+ Data->TransferMode |\
+ Data->DPSM);
+
+ /* Write to SDMMC DCTRL */
+ MODIFY_REG(SDMMCx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
+
+ 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 */
+ SDMMCx->DCTRL |= SDMMC_ReadWaitMode;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* (HAL_SD_MODULE_ENABLED) || (HAL_MMC_MODULE_ENABLED) */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/hal/f7/src/stm32f7xx_ll_usb.c b/stmhal/hal/f7/src/stm32f7xx_ll_usb.c
new file mode 100644
index 0000000000..8266b09a7a
--- /dev/null
+++ b/stmhal/hal/f7/src/stm32f7xx_ll_usb.c
@@ -0,0 +1,1696 @@
+/**
+ ******************************************************************************
+ * @file stm32f7xx_ll_usb.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 25-June-2015
+ * @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) 2015 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 "stm32f7xx_hal.h"
+
+/** @addtogroup STM32F7xx_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);
+
+/** @defgroup PCD_Private_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)
+{
+ if (cfg.phy_itface == USB_OTG_ULPI_PHY)
+ {
+
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+
+ /* Init The ULPI Interface */
+ USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
+
+ /* Select vbus source */
+ USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
+ if(cfg.use_external_vbus == 1)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD;
+ }
+ /* Reset after a PHY select */
+ USB_CoreReset(USBx);
+ }
+ else /* FS interface (embedded Phy) */
+ {
+
+ /* 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;
+ }
+
+ if(cfg.dma_enable == ENABLE)
+ {
+ USBx->GAHBCFG |= (USB_OTG_GAHBCFG_HBSTLEN_1 | USB_OTG_GAHBCFG_HBSTLEN_2);
+ USBx->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN;
+ }
+
+ 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 the 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)
+ {
+ /*Desactivate 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;
+
+ if(cfg.phy_itface == USB_OTG_ULPI_PHY)
+ {
+ if(cfg.speed == USB_OTG_SPEED_HIGH)
+ {
+ /* Set High speed phy */
+ USB_SetDevSpeed (USBx , USB_OTG_SPEED_HIGH);
+ }
+ else
+ {
+ /* set High speed phy in Full speed mode */
+ USB_SetDevSpeed (USBx , USB_OTG_SPEED_HIGH_IN_FULL);
+ }
+ }
+ else
+ {
+ /* 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 the 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 the 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 the 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 the 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 the 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 the 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 the 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 the 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)
+{
+ 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;
+
+
+ if(USBx == USB_OTG_FS)
+ {
+ /* 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);
+
+ }
+
+ else
+ {
+ /* set Rx FIFO size */
+ USBx->GRXFSIZ = (uint32_t )0x200;
+ USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t )(((0x100 << 16)& USB_OTG_NPTXFD) | 0x200);
+ USBx->HPTXFSIZ = (uint32_t )(((0xE0 << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0x300);
+ }
+
+ /* 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 the 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 the 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 the 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 the 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 the 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;
+ }
+ else
+ {
+ if(USBx != USB_OTG_FS)
+ {
+ USBx_HC(ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_NYET | USB_OTG_HCINTMSK_ACKM);
+ }
+ }
+ 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 the 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;
+
+ if((USBx != USB_OTG_FS) && (hc->speed == USB_OTG_SPEED_HIGH))
+ {
+ if((dma == 0) && (hc->do_ping == 1))
+ {
+ USB_DoPing(USBx, hc->ch_num);
+ return HAL_OK;
+ }
+ else if(dma == 1)
+ {
+ USBx_HC(hc->ch_num)->HCINTMSK &= ~(USB_OTG_HCINTMSK_NYET | USB_OTG_HCINTMSK_ACKM);
+ hc->do_ping = 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) */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/